集合三——Set

it2022-06-25  105

Set接口继承了Collection接口,因此Set的实现类HashSet和TreeSet都具有add()和remove()还有迭代器iterator()方法。


HashSet:


HashSet是一个散列集,可以快速查找对象。 HashSet用链表数组实现,数组里存放一个链表。 HashSet存放对象时会先在集里面查找是否存在这个对象如果不存在才会将对象放到集里。 其过程一般为: 获取这个对象的哈希码(散列码),然后与桶的总数(数组长度)取余,所得结果就是保存这个对象的桶的索引,然后遍历桶里的对象看是否有与要加进来的对象相同,没有就加进来。 这个过程中有一个理想情况,即恰好每一个桶里只有一个对象,不过既然是理想的就很难实现。所以人们一般将桶数设计为元素个数的75%-150%。标准类库使用的桶数是2的幂,这样可以防止元素过多的聚集在一个桶里。 填装因子:当散列表存储的元素达到一个界限时就会在散列,即再创建一个桶数更多的表,并将元素插入这个表,原来的表会被抛弃。这个界限就是填装因子,一个位于0-1之间的数。 遍历: HashSet提供一个迭代器hasSet.iterator()。

Set<String> set = new HashSet<>(); for(int i = 0;i<10;i++) { set.add("" + i); } Iterator<String> it = set.iterator(); while(it.hasNext()){ String str = it.next(); System.out.println(str); } }

这是常见的for循环遍历。 还可以用for each循环。

for(String string : set) { System.out.println(string); }

for each可以与任何实现了Iterable接口的对象一起工作。Collection接口扩展了Iterator接口。 Iterator接口有个默认方法forEachRemaining().

it.forEachRemaining(str->System.out.println(str));

这样也可以实现遍历,这是JAVA SE 8的新特性。 构造器: HashSet() HashSet(Collection<? extents E> elements) HashSet(int init) HashSet(int init,float load) :构造一个具有指定容量和填装因子的空散列表。


TreeSet:


树集是一个有序的集合,这个有序并不是插入的顺序,而是按树集使用的比较器进行排序的。 每次将一个元素添加到树中时,都会被放置在正确的顺序,并不是按插入顺序排序。因此迭代器会按排好序的顺序访问每个元素。 树集添加元素比散列集慢,但比List快。 因为树集要排序,因此添加进树集的元素要能比较。 使用树集的时候我们可以自定义比较器,下面将说道如何定义比较器。 先看一下树集的构造器: TreeSet(); TreeSet(Comparator<? super E> comparator); 创建一个指定比较器空的树集。(这个稍后会讲) TreeSet(Collection <? extends E> elem); TreeSet(SortedSet s); 增加一有序集中的所有元素。

TreeSet(Comparator<? super E> comparator): Comparator是一个功能接口,它提供了许多的静态方法来创建比较器。这里介绍一个简单的列子。 这里有一个类:

public class Item { private String description; private int partNumber; ..... }

如果将Item的多个对象存进TreeSet里并按partNumber关键字排序。 可以创建这样一个树集:

Set<Item> sortSet = new TreeSet<>( Comparator.comparing(Item::getDescription));

还可以把比较器与thenComparing方法串起来。

Set<Item> sortSet = new TreeSet<>( Comparator.comparing(Item::getDescription).thenComparing(Item::getPartNumber));

更多的比较器请看JAVA1.8文档

如果不使用指定比较器的构造方法去创建一个TreeSet,就直接添加Item对象会报错

java.lang.ClassCastException

因为TreeSet的元素必须是可比较的。 如果不想这样,还可以让Item实现Comparable接口。 Comparable接口只有一个方法: compareTo(T o)

public class Item implements Comparable<Item> { private String description; private int partNumber; public int compareTo(Item other) { int diff = Integer.compare(partNumber, other.partNumber); return diff != 0 ? diff : description.compareTo(other.description); } }

这样Item就是可比较的。这里按数值大小排序。


最新回复(0)