Set
Set接口继承Collection接口,完全接收了Collection里定义的方法,无扩展方法。
AbstractSet
抽象类,继承AbstractCollection类,实现Set接口,在类中,模板方式实现了 equals、hashCode、removeAll三个方法。
HashSet
继承AbstractSet类,实现Set接口,常用。
底层实现是个map,key是我们放进去的对象,value都是同一个object。
private static final Object PRESENT = new Object();
这个map常用情况下是HashMap
public HashSet() {
map = new HashMap<>();
}
但是HashSet预留了一个构造方法,供它的子类LinkedHashSet调用,此时使用LinkedHashMap
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
HashSet里的方法的内部实现逻辑,可看作是对这个map进行的方法调用。
LinkedHashSet
继承HashSet类,实现Set接口。
类内部只定义了构造方法,每个构造方法都会访问super,调用HashSet里预留的一个被LinkedHashMap实现的map的方法。
与HashSet的区别在于它会记录元素插入集合的顺序,并按照此顺序迭代输出。
public static void testSet(){
Set<Integer> set1 = new HashSet<Integer>();
set1.add(8);
set1.add(5);
set1.add(12);
set1.add(4);
System.out.println(set1);
Set<Integer> set2 = new LinkedHashSet<Integer>();
set2.add(8);
set2.add(5);
set2.add(12);
set2.add(4);
System.out.println(set2);
}
输出结果:
[4, 5, 8, 12]
[8, 5, 12, 4]
SortedSet
接口,继承Set接口,并进行了方法扩展。
SortedSet是一个对集合元素自动排序的接口,它要求被添加的元素都实现了Comparable接口。它默认是按照从小到大的顺序去排列添加进去的元素(通过控制Comparable的实现方法确定顺序方式)。
SortedSet在Set接口的基础上扩展了如下方法:
- comparator,返回用于排序此集合中元素的比较器,如果此集合使用其元素的{@linkplain Comparable自然排序},则返回null。非元素的比较器指自定义的,当作参数传给实现类构造方法的比较器。构造方法传进来的比较器会覆盖元素本身的比较器。相同的元素不添加。
- first,返回排序后的第一个元素
- last,返回排序后的最后一个元素
- headSet,传入一个元素,获取这个元素之前的所有元素作为新的Set,不包括能匹配到的这个元素,新Set里的元素修改会影响原Set
- tailSet,传入一个元素,获取这个元素之后的所有元素作为新的Set,包括能匹配到的这个元素,新Set里的元素修改会影响原Set
- subSet,传入两个元素,截取这俩元素直接的元素作为新的Set集合,新Set里的元素修改会影响原Set
public class Cat implements Comparable<Cat> {
private int id;
private String name;
public Cat(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public int compareTo(Cat o) {
return o.getId() - this.id;
}
@Override
public String toString() {
return "Cat{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public static void testSortedSet(){
Cat cat1 = new Cat(7, "seven");
Cat cat2 = new Cat(5,"five");
Cat cat3 = new Cat(9,"nine");
Cat cat4 = new Cat(5,"five2");
Comparator<Cat> ageComparator = Comparator.comparing(Cat::getId);
SortedSet<Cat> sortedSet = new TreeSet<>(ageComparator);
sortedSet.add(cat1);
sortedSet.add(cat2);
sortedSet.add(cat3);
sortedSet.add(cat4);
System.out.println(sortedSet);
System.out.println(sortedSet.comparator());
System.out.println(sortedSet.first());
System.out.println(sortedSet.last());
System.out.println(sortedSet.headSet(cat2));
System.out.println(sortedSet.tailSet(cat2));
System.out.println(sortedSet.subSet(cat2, cat3));
}
输出结果:
[Cat{id=5, name='five'}, Cat{id=7, name='seven'}, Cat{id=9, name='nine'}]
java.util.Comparator$$Lambda$2/668386784@15aeb7ab
Cat{id=5, name='five'}
Cat{id=9, name='nine'}
[]
[Cat{id=5, name='five'}, Cat{id=7, name='seven'}, Cat{id=9, name='nine'}]
[Cat{id=5, name='five'}, Cat{id=7, name='seven'}]
NavigableSet
继承SortedSet接口,是对Sorted接口方法的扩展
- lower,返回集合中小于输入参数的最大元素
- floor,返回集合中小于等于输入元素的最大元素
- ceiling,返回集合中大于等于输入元素的最小元素
- higher,返回集合中大于输入元素的最小元素
- pollFirst,返回集合里排序后的第一个元素
- pollLast,返回集合里排序后的最后一个元素
- headSet、tailSet、subSet都带有了Boolean参数,表示结果里是否要带有与输入参数相等的元素。
- descendingSet,生成该集合的逆序集合
- descendingIterator,逆序集合的迭代
TreeSet
继承AbstractSet类,实现NavigableSet接口。
底层也是使用map,不过使用的是TreeMap。构造器方法支持传入比较器作为参数。
实现接口的相关方法,内部逻辑也是调用map的相关方法,只是把map里的key作为了set的主要数据集合。(map的源码解释后续会编写)