java 集合之Set

    java集合类是实际开发中经常使用到的工具类。java集合大致可以分为Set(无序、不可重复),List(有序、重复),Map(key、value键值对),Queue(队列,JDK1.5添加)四大体系。collection体系继承树:

java 集合之Set

Map体系集成树:

java 集合之Set

                                                  Collection

Collection所有方法(JDK1.8):

boolean add(E e)
Ensures that this collection contains the specified element (optional operation).
boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection (optional operation).
void clear()
Removes all of the elements from this collection (optional operation).
boolean contains(Object o)
Returns true if this collection contains the specified element.
boolean containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the specified collection.
boolean equals(Object o)
Compares the specified object with this collection for equality.
int hashCode()
Returns the hash code value for this collection.
boolean isEmpty()
Returns true if this collection contains no elements.
Iterator<E> iterator()
Returns an iterator over the elements in this collection.
default Stream<E> parallelStream()
Returns a possibly parallel Stream with this collection as its source.
boolean remove(Object o)
Removes a single instance of the specified element from this collection, if it is present (optional operation).
boolean removeAll(Collection<?> c)
Removes all of this collection's elements that are also contained in the specified collection (optional operation).
default boolean removeIf(Predicate<? super E> filter)
Removes all of the elements of this collection that satisfy the given predicate.
boolean retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the specified collection (optional operation).
int size()
Returns the number of elements in this collection.
default Spliterator<E> spliterator()
Creates a Spliterator over the elements in this collection.
default Stream<E> stream()
Returns a sequential Stream with this collection as its source.
Object[] toArray()
Returns an array containing all of the elements in this collection.
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array.

API截图:

java 集合之Set

Collection所有的子类都实现 Iterable<E> 接口

Iterator使用:
Iterator<String> it = c.iterator();
while(it.hasNext()){
String str = (String)it.next();

System.out.println(str);

                    

                    Set

Set:

    Set方法基本和Collection一样,没有添加任何方法,无序不能重复

HashSet(按hash算法来存储元素,集合值可以是null,不是同步的):继承Set方法

public class HashSet<E>
    extends AbstractSet<E>

    implements Set<E>, Cloneable, java.io.Serializable

HashSet使用到HashMap,如下图(只贴出部分函数,具体方式自己查看API):

    private transient HashMap<E,Object> map;

java 集合之Set

HashSet 判断两个元素的标准是:equals()方式返回true,并且hashCode()方法返回值也相等;

代码演示:

public class OverrideEquals{
//重写equals()
public boolean equals(Object obj){
return true;
}

}

public class OverrideHashCode {
//重写hashCode()
public int hashCode(){
return 0;
}

}

public class OverrideAll {
//重写这两个方法
public boolean equals(Object obj){
return true;
}
public int hashCode(){
return 2;
}

}

Set<Object> hash = new HashSet<>();

hash.add(new OverrideEquals());
hash.add(new OverrideEquals());
hash.add(new OverrideHashCode());
hash.add(new OverrideHashCode());
hash.add(new OverrideAll());
hash.add(new OverrideAll());

System.out.println(hash);

结果如图:

java 集合之Set

注意:HashSet存值得时候,如果equals()返回的结果都为true,hashCode()返回的结果不一样时,根据hashCode值进行存储(这种方式与Set规则有点出入),如果hashCode()返回的值一样,equals()返回false,根据hashCode定位存值的方式,不可能把两个值放在一起,这个时候用链式来存储这两个对象,这样会导致性能下降。

JDK1.8里面加入了新的方法:

Spliterator<E> spliterator()
在此集合中的元素上创建late-binding故障快速 Spliterator
我在看源码时才发现的,先看看官方文档上Spliterator<E> 的介绍:
  • 用于遍历和分割源的元素的对象。 Spliterator涵盖的元素的来源可以是例如阵列, Collection ,IO通道或生成器函数。   

大致方法:

int characteristics()
返回此Spliterator及其元素的一组特征。
long estimateSize()
返回 forEachRemaining(java.util.function.Consumer<? super T>)遍历将遇到的元素数量的估计,如果无穷大,未知数或计算 成本太高,则返回 Long.MAX_VALUE
default void forEachRemaining(Consumer<? super T> action)
在当前线程中依次执行每个剩余元素的给定操作,直到所有元素都被处理或动作引发异常。
default Comparator<? super T> getComparator()
如果这个Spliterator的来源是SORTEDComparator ,返回Comparator
default long getExactSizeIfKnown()
方便的方法返回 estimateSize()如果这个Spliterator是 SIZED ,否则 -1
default boolean hasCharacteristics(int characteristics)
返回 true如果Spliterator的 characteristics()包含所有给定的特性。
boolean tryAdvance(Consumer<? super T> action)
如果剩下的元素存在,执行给定的操作,返回true ; 否则返回false
Spliterator<T> trySplit()
如果此分割器可以被分区,返回一个包含元素的Spliter,当从该方法返回时,它不会被该Spliter所覆盖。 

与Iterator的区别就是一个是顺序遍历,一个是并行遍历。测试了几个方法,部分代码:

Set<Object> hash = new HashSet<>();
hash.add("begin");
hash.add("hello");
hash.add("set");

hash.add("end");

Spliterator<Object> s = hash.spliterator();

// 返回此Spliterator及其元素的一组特征
System.out.println("s characteristics():"+s.characteristics());
Spliterator<Object> b = s.trySplit();
System.out.println(s.tryAdvance(test -> System.out.println("b forEachRemaining:"+test)));
// 在当前线程中依次执行每个剩余元素的给定操作,直到所有元素都被处理或动作引发异常。
s.forEachRemaining(test -> System.out.println("s forEachRemaining:"+test));
b.forEachRemaining(test -> System.out.println("b forEachRemaining:"+test));
//如果剩下的元素存在,执行给定的操作,返回true ; 否则返回false 。

System.out.println(s.tryAdvance(test -> System.out.println("b forEachRemaining:"+test)));

运行结果:

s characteristics():65
b forEachRemaining:end
true
s forEachRemaining:hello
s forEachRemaining:begin
b forEachRemaining:set
false