JDK源码阅读 - 04 集合 之 Set

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的源码解释后续会编写)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值