Java基础(十七)——Set集合、可变参数和Collections工具类

Set接口

  java.util.set接口和java.util.List接口是一样的,都是继承自Collection接口,它与collection接口中的方法基本一样,没有对Collection接口进行功能上的扩展,只是比Collection接口更加严格。与List接口不同的是,Set接口中的元素是无序的,并且都会以某种规则保证存入的元素不重复。

  Set集合取出元素的方式可以采用:迭代器、增强for循环。

HashSet集合介绍

  java.util.HashSet是Set接口的一个实现类,它存储的元素是不可重复的,并且元素都是无序的(存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持的。

  HashSet是根据对象的哈希值来确定元素在集合当中的存储位置,因此它具有良好的存取和查找性能。保证元素唯一性的方式依赖于hashCodeequals方法。

  实例代码:

 

 1         //创建HashSet集合对象
 2         HashSet<String> hashSet = new HashSet<>();
 3         String str01 = new String("abc");
 4         String str02 = new String("abc");
 5         hashSet.add(str01);
 6         hashSet.add(str02);
 7         hashSet.add("种地");
 8         hashSet.add("通话");
 9         hashSet.add("abc");
10         System.out.println(hashSet);//[通话, abc, 种地]
11         //依赖于hashCode和equals方法
12  

 

 

 

HashSet集合存储数据的结构(哈希表)

  什么是哈希表呢?

  在JDK1.8之前,哈希表的底层采用的是数组+链表实现,即使用链表处理哈希冲突,同一哈希值的链表都存储在一个链表里,但是当位于一个链中的元素较多时,即hash值相等的元素较多时,通过key值依次查找的效率很低下。在JDK1.8中,哈希表存储结构采用数组+链表/红黑树实现的,当链表的长度超过阈值(8)时,将链表转换成红黑树结构,这样的好处是大大减少了查找的时间。

  如图展示:

哈希表结构概述

 

 

 

  总而言之,JDK1.8之后引入红黑树结构大大优化了HashMap的性能,那么对于我们来讲保证HashSet元素唯一不重复,其实是根据对象的hashCode和equals方法来决定的。如果我们往集合当中存储的是自定义的对象,需要保证对象的唯一性,就必须重写hashCode和equals方法,来自定义当前的对象的比较方式。

  HashSet保证元素唯一的原理,如图所示

HashSet保证元素唯一的原理介绍

 

 

 HashSet存储自定义类型的元素

    一般需要重写对象当中的hashCode和equals方法,建立自己的比较方式。才能保证HashSet集合中元素的唯一性。

  代码示例:

 1 @Override
 2     public boolean equals(Object o) {
 3         if (o == null) {
 4             return false;
 5         }
 6         if (this == o) {
 7             return true;
 8         }
 9         // 向下转型 类型判断
10         if (o instanceof Student) {
11             Student student = (Student)o;
12             // 同名同年龄的人为同一个人 true
13             return student.getName().equals(name) && student.getAge() == age;
14         }
15         return false;
16     }
17 
18     @Override
19     public int hashCode(){
20          // 使用Objects类中的hash方法
21         return Objects.hash(name,age);
22     }

LinkedHashSet集合

   我们知道HashSet保证元素的唯一,可是存进去的元素是没有顺序的,那么如何保证存进去的元素是有序的?

  在java.util.HashSet类的下面还有一个子类java.util.LinkedHashSet,它是链表和哈希表的组合的一个数据存储结构。代码示例:

    

 1 // 构建一个LinkedHashSet集合对象
 2         LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
 3         linkedHashSet.add("www");
 4         linkedHashSet.add("baidu");
 5         linkedHashSet.add("com");
 6         linkedHashSet.add("abc");
 7         linkedHashSet.add("abc");
 8         linkedHashSet.add("java");
 9         linkedHashSet.add("python");
10         // [www, baidu, com, abc, java, python]
11         System.out.println(linkedHashSet);// [www, baidu, com, abc] 有序的,不重复的

可变参数

   在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数的数据类型一致,那么我们可以简化成如下格式:

1 修饰符 返回值类型  方法名(参数类型... 形参名){
2     //...
3 }

  其实上面的格式完全等价于:

1 修饰符 返回值类型  方法名(参数类型[] 参数名){
2     //....
3 }

  只是后面的写法,在方法调用,必须传递一个数组类型,而前者可以直接传递参数数据。

  JDK1.5之后,出现的这种简化操作。"..."用在参数上,我们称之为可变参数。

  同样是代表数组,但是在方法调用这个带有可变参数时,不用创建数组,而是直接将数组当中的元素作为实际参数进行传递,其实编译生成的.class文件,本质是将这些元素封装到了一个数组当中,再进行数据传递,这些动作都在编译生成.class文件的时候,自动完成了。

  代码示例:

1  public static void add(int... arr) {
2         //System.out.println(arr);// [I@1b6d3586 底层就是一个数组
3         //System.out.println(arr.length);//0
4         int sum = 0;
5         for (int i = 0; i < arr.length; i++) {
6             sum += arr[i];
7         }
8         System.out.println(sum); // 30
9     }

  Collections集合工具类

    常用功能

 

  • java.util.Collections是集合工具类,用来操作集合对象中的元素, 方法如下:
  • public static <T> boolean addAll(Collection<? super T> c,T... elements):往集合中一次性添加多个元素。
  • public static <T> void shuffle(List<?> list):打乱集合中的元素顺序。
  • public static <T> void sort(List<T> list):将集合中的元素按照默认规则排序。
  • public static <T> void sort(List<T> list,Comparator<? super T> c):将集合中的元素按照指定的规则进行排序。

 

代码演示:

  

 1         ArrayList<String> strs = new ArrayList<>();
 2         //往集合当中存储元素
 3         /*strs.add("abc");
 4         strs.add("小孙");
 5         strs.add("小刘");
 6         strs.add("小赵");*/
 7 
 8         //使用Collections集合工具类中的addAll
 9         Collections.addAll(strs, "张三","老王","小金豆","孬蛋","老白干");
10         System.out.println(strs);
11         System.out.println("=========================");
12         Collections.shuffle(strs);
13         System.out.println(strs);    
 1 ArrayList<Integer> list01 = new ArrayList<>();
 2 Collections.addAll(list01, 124,234,566,324,765,342);
 3 System.out.println(list01);
 4        System.out.println("============================");
 5 Collections.sort(list01);
 6 System.out.println(list01);
 7         System.out.println("============================");
 8 ArrayList<String> list02 = new ArrayList<>();
 9         Collections.addAll(list02,"asd","sd","sc","sv","ac","b","vc","v","cs");
10 Collections.shuffle(list02);
11 Collections.sort(list02);
12 System.out.println(list02);

 

posted @ 2020-12-03 21:32  寒江雨  阅读(373)  评论(0编辑  收藏  举报