Java集合(3)——基础介绍(3)——可变参数、Collections工具类、Map接口

本文深入讲解Java集合框架,包括可变参数、Collections工具类、Map接口及其实现类如HashMap、LinkedHashMap、Hashtable,探讨Map集合的遍历方法,介绍JDK9对集合的优化,并提供实战案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.可变参数

2.Collections工具类

3.Map接口

3.1 Map接口的常用实现类

3.2 Map接口的常用方法

3.3 遍历Map集合的两种方式

3.4 HashMap存储自定义类型键值

3.5 LinkedHashMap

3.5 HashTable

3.6 Map集合练习

4. JDK9对集合添加的优化

5.双列集合模拟斗地主洗牌发牌


1.可变参数

可变参数是JDK 1.5之后出现的新特性

使用前提:

  • 当方法的参数列表的数据类型已经确定,但是参数的个数不确定,就可以使用可变参数

使用格式:

  • 修饰符  返回值类型   方法名(数据类型...变量名

可变参数的原理:

  • 可变参数底层是一个数组,根据传递参数个数的不同,会创建不同长度的数组,来存储这些参数
  • 传递的参数可以是0个或多个

示例代码:

package com.boboyu;

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(add());
        System.out.println(add(1,2));
        System.out.println(add(1,2,3,4,5,6,7,8,9,10));

    }

    /*
    定义计算0-n整数和的方法
    已知:计算整数和,数据类型已经确定为int
    但是参数个数不确定,不知道要计算几个整数的和,就可以使用可变参数
     */
    public static int add(int...arr)
    {
        System.out.println("-----------------");
        System.out.println(arr);
        System.out.println(arr.length);
        int sum=0;
        for (int i : arr) {
            sum+=i;
        }
        return sum;
    }
}

可变参数的注意事项:

  • 1.一个方法的参数列表,只能有一个可变参数
  • 2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾

Java源码中可变参数的终极写法:

public static void method(Object...obj){//Object可以接收任意数据类型的参数

}

2.Collections工具类

java.utils.Collections是集合工具类,用来对集合进行操作。

部分方法如下:

代码演示:

package com.boboyu;

import java.util.ArrayList;
import java.util.Collections;

public class Demo01 {
    public static void main(String[] args) {
        ArrayList<String> arr=new ArrayList<>();
        //往集合中添加多个元素
        Collections.addAll(arr,"a","b","c","d");
        System.out.println(arr);

        //打乱arr集合中的元素顺序
        Collections.shuffle(arr);
        System.out.println(arr);
    }
}

示例代码1:

package com.boboyu;

import java.util.ArrayList;
import java.util.Collections;

public class Demo01 {
    public static void main(String[] args) {
        ArrayList<Integer> list01=new ArrayList<>();
        //往集合中添加多个元素
        Collections.addAll(list01,1,3,2);
        System.out.println(list01);

        Collections.sort(list01);//将集合中的元素按照默认规则排序,默认是升序
        System.out.println(list01);

        ArrayList<String> list02 = new ArrayList<>();
        Collections.addAll(list02,"a","c","b");
        System.out.println(list02);

        Collections.sort(list02);
        System.out.println(list02);

    }
}

注意:

  • sort方法使用的前提:被排序的集合中存储的元素,必须实现Comparable接口,重写它其中的comapareTo方法

可以看到在Integer类和String类的源码中都是实现了Comparable接口,重写了它其中的comapareTo方法

Integer:

String:

所以对于自定义的类,要在集合中存储,并使用Collections中的sort方法进行排序的话,我们需要实现Comparable接口,并重写它的compareTo方法

示例代码:

Person.java

package com.boboyu;

public class Person implements Comparable<Person>{
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    //重写排序的规则
    @Override
    public int compareTo(Person o) {
        //自定义比较的规则,比较两个人的年龄
        //return this.getAge() - o.getAge();//升序排序
        return o.getAge() - this.getAge();//降序排序
    }
}

Demo01.java

package com.boboyu;

import java.util.ArrayList;
import java.util.Collections;

public class Demo01 {
    public static void main(String[] args) {
        ArrayList<Person> list03=new ArrayList<>();
        list03.add(new Person("Lily",18));
        list03.add(new Person("Luck",20));
        list03.add(new Person("Mark",15));
        System.out.println(list03);
        Collections.sort(list03);
        System.out.println(list03);
    }
}

Comparable和Comparator:

  • Comparable:自己(this)和别人比较,自己需要实现Comparable接口,重写比较的方法compareTo方法
  • Comparator:相当于找一个第三方的裁判,比较两个

示例代码:

Person.java

package com.boboyu;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}'+"\n";
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

Demo01.java

package com.boboyu;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Demo01 {
    public static void main(String[] args) {
        ArrayList<Person> list03=new ArrayList<>();
        list03.add(new Person("Lily",18));
        list03.add(new Person("Amy",18));
        list03.add(new Person("Luck",20));
        list03.add(new Person("Mark",15));
        System.out.println("排序前");
        System.out.println(list03);
        System.out.println("-----------------------");
        Collections.sort(list03, new Comparator<Person>() {
            //重写比较的规则
            @Override
            public int compare(Person o1, Person o2) {
                int result = o1.getAge() - o2.getAge(); //按照年龄的升序进行排序

                if(result==0)
                {
                    result = o1.getName().charAt(0) - o2.getName().charAt(0);
                }

                return result;
            }
        });

        System.out.println("排序后");
        System.out.println(list03);
    }
}

3.Map接口

Map集合的特点:

  • 1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
  • 2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
  • 3.Map集合中,key是不允许重复的,value是可以重复的
  • 4.Map集合中,key和value是一一对应的,即一个key对应一个value

3.1 Map接口的常用实现类

(1)HashMap

特点:

  • 1.底层是哈希表,JDK1.8之前是数组+链表,JDK1.8之后是数组+链表/红黑树(链表的长度超过8),提高查询速度
  • 2.hashMap是一个无序的集合,存储元素的顺序和取出元素的顺序有可能不一致

(2)LinkedHashMap

特点:

  • 1.底层是哈希表+链表(保证迭代的顺序)
  • 2.LinkedHashMap是一个有序的集合,存储元素的顺序和取出元素的顺序是一致的

3.2 Map接口的常用方法

package com.boboyu;

import java.util.HashMap;
import java.util.Map;

public class Demo01 {
    public static void main(String[] args) {
        show01();
    }

    /*
    public V put(K key, V value):  把指定的键与指定的值添加到Map集合中。
        返回值:v
            存储键值对的时候,key不重复,返回值V是null
            存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
 */
    private static void show01() {
        //创建Map集合对象,多态
        Map<String,String> map = new HashMap<>();

        String v1 = map.put("李晨", "范冰冰1");
        System.out.println("v1:"+v1);//v1:null

        String v2 = map.put("李晨", "范冰冰2");
        System.out.println("v2:"+v2);//v2:范冰冰1

        System.out.println(map);//{李晨=范冰冰2}

        map.put("冷锋","龙小云");
        map.put("杨过","小龙女");
        map.put("尹志平","小龙女");
        System.out.println(map);//{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
    }
}

package com.boboyu;

import java.util.HashMap;
import java.util.Map;

public class Demo01 {
    public static void main(String[] args) {
        show03();
    }
    /*
    public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
        返回值:
            key存在,返回对应的value值
            key不存在,返回null
 */
    private static void show03() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        Integer v1 = map.get("杨颖");
        System.out.println("v1:"+v1);//v1:165

        Integer v2 = map.get("迪丽热巴");
        System.out.println("v2:"+v2);//v2:null
    }
}

package com.boboyu;

import java.util.HashMap;
import java.util.Map;

public class Demo01 {
    public static void main(String[] args) {
        show02();
    }

    /*
      public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
          返回值:V
              key存在,v返回被删除的值
              key不存在,v返回null
   */
    private static void show02() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);
        System.out.println(map);//{林志玲=178, 赵丽颖=168, 杨颖=165}

        Integer v1 = map.remove("林志玲");
        System.out.println("v1:"+v1);//v1:178

        System.out.println(map);//{赵丽颖=168, 杨颖=165}

        //int v2 = map.remove("林志颖");//自动拆箱  NullPointerException
        Integer v2 = map.remove("林志颖");
        System.out.println("v2:"+v2);//v2:null

        System.out.println(map);//{赵丽颖=168, 杨颖=165}
    }
}

package com.boboyu;

import java.util.HashMap;
import java.util.Map;

public class Demo01 {
    public static void main(String[] args) {
        show04();
    }
    /*
        boolean containsKey(Object key) 判断集合中是否包含指定的键。
        包含返回true,不包含返回false
     */
    private static void show04() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        boolean b1 = map.containsKey("赵丽颖");
        System.out.println("b1:"+b1);//b1:true

        boolean b2 = map.containsKey("赵颖");
        System.out.println("b2:"+b2);//b2:false
    }
}

3.3 遍历Map集合的两种方式

第一种方式:

示例代码:

package com.boboyu;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/*
    Map集合的第一种遍历方式:通过键找值的方式
    Map集合中的方法:
         Set<K> keySet() 返回此映射中包含的键的 Set 视图。
    实现步骤:
        1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        2.遍历set集合,获取Map集合中的每一个key
        3.通过Map集合中的方法get(key),通过key找到value
 */

public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        Set<String> set = map.keySet();

        //2.遍历set集合,获取Map集合中的每一个key
        //使用迭代器遍历Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : set){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : map.keySet()){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
    }

}

第二中方式:

示例代码:

package com.boboyu;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/*
    Map集合遍历的第二种方式:使用Entry对象遍历

    Map集合中的方法:
        Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

    实现步骤:
        1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        2.遍历Set集合,获取每一个Entry对象
        3.使用Entry对象中的方法getKey()和getValue()获取键与值
 */
public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();

        //2.遍历Set集合,获取每一个Entry对象
        //使用迭代器遍历Set集合
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
        System.out.println("-----------------------");
        for(Map.Entry<String,Integer> entry:set){
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
    }
}

3.4 HashMap存储自定义类型键值

Person.java

package com.boboyu;

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

Demo01.java

package com.boboyu;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
    Map集合遍历的第二种方式:使用Entry对象遍历

    Map集合中的方法:
        Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

    实现步骤:
        1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        2.遍历Set集合,获取每一个Entry对象
        3.使用Entry对象中的方法getKey()和getValue()获取键与值
 */
public class Demo01 {
    public static void main(String[] args) {
        show01();
        System.out.println("-----------------");
        show02();
    }

    /*
        HashMap存储自定义类型键值
        key:Person类型
            Person类就必须重写hashCode方法和equals方法,以保证key唯一
        value:String类型
            可以重复
     */
    private static void show02() {
        //创建HashMap集合
        HashMap<Person,String> map = new HashMap<>();
        //往集合中添加元素
        map.put(new Person("女王",18),"英国");
        map.put(new Person("秦始皇",18),"秦国");
        map.put(new Person("普京",30),"俄罗斯");
        map.put(new Person("女王",18),"毛里求斯");//重写了equals和hashCode方法保证了唯一
        //使用entrySet和增强for遍历Map集合
        Set<Map.Entry<Person, String>> set = map.entrySet();
        for (Map.Entry<Person, String> entry : set) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-->"+value);
        }
    }

    /*
        HashMap存储自定义类型键值
        key:String类型
            String类重写hashCode方法和equals方法,可以保证key唯一
        value:Person类型
            value可以重复(同名同年龄的人视为同一个)
     */
    private static void show01() {
        //创建HashMap集合
        HashMap<String,Person> map = new HashMap<>();
        //往集合中添加元素
        map.put("北京",new Person("张三",18));
        map.put("上海",new Person("李四",19));
        map.put("广州",new Person("王五",20));
        map.put("北京",new Person("赵六",18));//赵六替换了张三
        //使用keySet加增强for遍历Map集合
        Set<String> set = map.keySet();
        for (String key : set) {
            Person value = map.get(key);
            System.out.println(key+"-->"+value);
        }
    }
}

  • 当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法(如果忘记,请回顾HashSet存放自定义对象)。

  • 如果要保证map中存放的key和取出的顺序一致,可以使用java.util.LinkedHashMap集合来存放。

3.5 LinkedHashMap

示例代码:

package com.boboyu;

import java.util.HashMap;
import java.util.LinkedHashMap;

/*
    java.util.LinkedHashMap<K,V> entends HashMap<K,V>
    Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
    底层原理:
        哈希表+链表(记录元素的顺序)
 */
public class Demo01 {
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put("a","a");
        map.put("c","c");
        map.put("b","b");
        map.put("a","d");
        System.out.println(map);// key不允许重复,无序 {a=d, b=b, c=c}

        LinkedHashMap<String,String> linked = new LinkedHashMap<>();
        linked.put("a","a");
        linked.put("c","c");
        linked.put("b","b");
        linked.put("a","d");
        System.out.println(linked);// key不允许重复,有序 {a=d, c=c, b=b}
    }
}

3.5 HashTable

特点:

  • 1. Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
  •     HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
  • 2. HashMap集合(之前学的所有的集合):可以存储null值,null键
  •     Hashtable集合,不能存储null值,null键
  • 3. Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
  • 4.Hashtable的子类Properties依然活跃在历史舞台,Properties集合是一个唯一和IO流相结合的集合
public class Demo02Hashtable {
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();
        map.put(null,"a");
        map.put("b",null);
        map.put(null,null);
        System.out.println(map);//{null=null, b=null}

        Hashtable<String,String> table = new Hashtable<>();
        //table.put(null,"a");//NullPointerException
        //table.put("b",null);//NullPointerException
        table.put(null,null);//NullPointerException
    }
}

3.6 Map集合练习


分析:

代码实现:

package com.boboyu;

import java.util.HashMap;
import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        //1.使用Scanner获取用户输入的字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = sc.next();
        //2.创建Map集合,key是字符串中的字符,value是字符的个数
        HashMap<Character,Integer> map = new HashMap<>();
        //3.遍历字符串,获取每一个字符
        for(char c :str.toCharArray()){
            //4.使用获取到的字符,去Map集合判断key是否存在
            if(map.containsKey(c)){
                //key存在
                Integer value = map.get(c);
                value++;
                map.put(c,value);
            }else{
                //key不存在
                map.put(c,1);
            }
        }
        //5.遍历Map集合,输出结果
        for(Character key :map.keySet()){
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
    }
}

        
4. JDK9对集合添加的优化

package com.boboyu;

import java.util.List;
import java.util.Map;
import java.util.Set;

/*
   JDK9的新特性:
       List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素
       static <E> List<E> of​(E... elements)
       使用前提:
           当集合中存储的元素的个数已经确定了,不在改变时使用
    注意:
       1.of方法只适用于List接口,Set接口,Map接口,不适用于接接口的实现类
       2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
       3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常
*/
public class Demo01 {
    public static void main(String[] args) {
        List<String> list = List.of("a", "b", "a", "c", "d");
        System.out.println(list);//[a, b, a, c, d]
        //list.add("w");//UnsupportedOperationException:不支持操作异常

        //Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素
        Set<String> set = Set.of("a", "b", "c", "d");
        System.out.println(set);
        //set.add("w");//UnsupportedOperationException:不支持操作异常

        //Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20,"张三",19);////IllegalArgumentException:非法参数异常,有重复的元素
        Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);
        System.out.println(map);//{王五=20, 李四=19, 张三=18}
        //map.put("赵四",30);//UnsupportedOperationException:不支持操作异常
    }
}

5.双列集合模拟斗地主洗牌发牌

待补充
   

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值