赞
踩
是Collection的子接口,一个不包含重复元素的集合,set集合提供的方法与父接口Collection的方法完全一致,即没有关于下标的操作方法
set接口有两个常用的子实现类HashSet,TreeSet
HashSet实现了Set接口,底层是hash表(实际上底层是HashMap),该类不允许重复元素,不保证迭代顺序,即无序,(插入顺序和遍历顺序不一致)。
HashSet()
构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
HashSet(Collection<? extends E> c)
构造一个包含指定 collection 中的元素的新 set。
HashSet(int initialCapacity)
构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。
HashSet(int initialCapacity, float loadFactor)
构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。
HashSet类中的方法与父接口Set接口中的方法一致,即又跟Collection接口中的方法一致,所有的都能用
boolean add(E e)
如果此 set 中尚未包含指定元素,则添加指定元素。
boolean remove(Object o)
如果指定元素存在于此 set 中,则将其移除。
int size()
返回此 set 中的元素的数量(set 的容量)。
HashSet<Object> hashSet = new HashSet<>(); //空参 //System.out.println(hashSet); // hashSet.add(1); // hashSet.add(2); // hashSet.add(3); // hashSet.add(1); // hashSet.add(".."); // hashSet.add("邓"); // hashSet.add("森"); // hashSet.add("洋"); //重复元素去除,无序输出 //System.out.println(hashSet); //迭代遍历 // Iterator<Object> iterator = hashSet.iterator(); // while (iterator.hasNext()){ // Object next = iterator.next(); // System.out.print(next+" "); // } //foreach遍历 // for (Object o: hashSet // ) { // System.out.print(o+" "); // } //移除元素 // boolean remove = hashSet.remove(".."); // System.out.println(remove); //返回集合容量 // int size = hashSet.size(); // System.out.println(size); //构造方法HashSet(Collection o),去除ArrayList集合中的重复元素 // ArrayList<Object> list = new ArrayList<>(); // list.add(1); // list.add(1); // list.add(2); // list.add(2); // list.add(3); // list.add(3); // list.add(4); // list.add(4); // HashSet<Object> hashSet1 = new HashSet<>(list); // System.out.println(hashSet1); //判断是否为空 //System.out.println(hashSet.isEmpty()); //判断是否包含指定元素 // boolean contains = hashSet.contains(1); // System.out.println(contains); //判断是否包含所有元素 // boolean b = hashSet.containsAll(hashSet); // System.out.println(b); //将指定集合放到hashset集合中,去除重复 // boolean b = hashSet.addAll(list); // System.out.println(b); // System.out.println(hashSet); //清空集合 // hashSet.clear(); // System.out.println(hashSet); //移除集合HashSet中的ArrayList集合的元素 // boolean b = hashSet.removeAll(list); // System.out.println(b); // System.out.println(hashSet);
HashSet底层是Hash表,其实是HashMap,初始容量16,加载因子 0.75,扩容的阈值 = 容量 * 0.75 ,超过阈值就触发扩容,扩容2倍,初始容量和加载因子可以通过构造方法创建时修改的。
1,调用add(E,e)方法时,会在底层调用元素e的hashcode方法来获得对象的地址值
2,如果地址值不一样,直接存储
3,如果地址值一样,会再调用元素的equals方法判断内容是否一样
4,如果equals不一样,那么就存储,如果equals判断为true,那么去重
LinkedHashSet既有HashSet的去重又有Linked结构有序的特性,即存储在LinkedHashSet中的元素既有不允许重复,又能保证迭代顺序
LinkedHashSet<Integer> integers = new LinkedHashSet<>();
//既有序,又去重
integers.add(111);
integers.add(222);
integers.add(333);
integers.add(12);
integers.add(222);
System.out.println(integers);
}
TreeSet是基于基于TreeMap的NavigableSet实现,可以使用元素的自然顺序对元素进行排序或者根据创建的set时提供的Comparator进行排序,具体取决于使用的构造方法,即TreeSet会对存储的元素排序,当然也会去重
构造方法:
TreeSet()
构造一个新的空set,set根据其元素的自然顺序进行排序。
TreeSet(Comparator<? super E> comparator)
构造一个新的空TreeSet,它根据指定比较器进行排序。
方法:
有常规的集合的方法,还有一些基于数据结构能排序的特性才有的特殊方法,取值范围的(ceiling(),floor(),lower(),higher(),),首尾取值的(first(),last())
TreeSet<Integer> treeSet= new TreeSet<>(); //去重(不能存储重复元素)并排序(升序) treeSet.add(3); treeSet.add(2); treeSet.add(4); treeSet.add(1); treeSet.add(3); //System.out.println(treeSet); for (Integer integer : treeSet) { //System.out.println(integer); } //获得排序后的第一个 //System.out.println(treeSet.first()); //获得排序后的最后一个 //System.out.println(treeSet.last()); //System.out.println(treeSet); //获取并移除排序后的第一个 //System.out.println(treeSet.pollFirst()); //获取并移除排序后的最后一个 //System.out.println(treeSet.pollLast()); //集合中已经不存在拿出的元素 //System.out.println(treeSet); //返回此set中严格小于给定元素的最大元素 System.out.println(treeSet.lower(100));
前提知识: TreeSet底层是TreeMap,TreeMap是红黑树,是一种平衡二叉树(AVL)
练习1:新建User类(age,name),创建TreeSet集合,创建多个User对象,将user对象存入TreeSet集合,实现去重排序,1) 年龄和姓名一致则去重 2) 按照年龄从小到大排序
TreeSet<User> set = new TreeSet<>( );
set.add(new User(18,"厄加特"));
// 运行报错ClassCastException 无法转成Comparable接口
Comparable接口,强行对实现它的每个类的对象进行整体排序,这种排序被称为类的自然排序.
实现这个接口,需要重写comparTo方法,该方法返回值决定了是升序,降序还是去重!
该comparTo(T t)方法运行时 , this指代当前正在调用该方法的对象,参数T就是之前已经存在的元素.
- 返回值 0 ,意味着此元素(正在存储的元素)和之前的元素相同,即不存储,则去重
- 返回值正整数,意味着此元素 大于之前的元素, 放在该节点的右边
- 返回值负整数,意味着此元素小于之前的元素,放在该节点的左边
最后都存储完毕时,取值时采用中序遍历(从根节点开始按照左,中,右的顺序读取)
public class User implements Comparable<User>{ // 属性和方法... /** * this 是指代正在存储的元素 * o 是之前存储的元素 */ @Override public int compareTo(User o) { System.out.println("此对象--> " + this); System.out.println("指定对象--> " + o); // 姓名和年龄相同返回0,即去重不存储 if (this.name.equals(o.getName()) && this.getAge() - o.getAge() == 0) { return 0; } // 年龄相同返回1,即保留下来的不去重的意思 // 年龄不同的话就正常相减,返回负数或正数 return this.getAge() - o.getAge() == 0 ? 1 : this.getAge() - o.getAge(); }
HashSet方法与父接口Collection中的方法一致,直接用,面试题:HashSet底层(HashMap),扩容,去重原理
LinkedHashSet 了解:
TreeSet底层树结构了解就行,只需要知道要想去重排序,必须要实现接口重写方法,返回0去重,返回负放左子树,返回正放右子树
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。