zoukankan      html  css  js  c++  java
  • HashSet、LinkedHashSet学习笔记


    一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

    注:如果将可变对象用作 set 元素,那么必须极其小心。如果对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不确定的。此项禁止的一个特殊情况是不允许某个 set 包含其自身作为元素。

    AbstractSet

    此抽象类重写AbstractCollection的任何方法,只是单独的增加了equalshashCode 的实现

    public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
    
        protected AbstractSet() {
        }
    
        // 比较指定对象与此 set的相等性,如果指定的对象也是一个set,并且两个set有相同的大小,元素,则返回true。
        public boolean equals(Object o) {
            if (o == this)
                return true;
    
            //1.先检查指定的对象是不是set
            if (!(o instanceof Set))
                return false;
            Collection<?> c = (Collection<?>) o;
            //2.再检查指定set的大小与这个set的大小是否相等
            if (c.size() != size())
                return false;
            try {
                //3.最后检查这个set是否包含指定set中的所有元素
                return containsAll(c);
            } catch (ClassCastException unused)   {
                return false;
            } catch (NullPointerException unused) {
                return false;
            }
        }
    
        //返回此set的哈希码值:即该set中所有元素的哈希值之和
        public int hashCode() {
            int h = 0;
            Iterator<E> i = iterator();
            while (i.hasNext()) {
                E obj = i.next();
                if (obj != null)
                    h += obj.hashCode();
            }
            return h;
        }
    
        //从此 set中移除包含在指定 collection中的所有元素
        public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            boolean modified = false;
    
            //如果此set的大小>指定集合c的大小
            if (size() > c.size()) {
                //迭代指定集合c中的元素,并在此set中逐个删除
                for (Iterator<?> i = c.iterator(); i.hasNext(); )
                    modified |= remove(i.next()); 
            } else {
                for (Iterator<?> i = iterator(); i.hasNext(); ) {
                    if (c.contains(i.next())) {
                        i.remove();
                        modified = true;
                    }
                }
            }
            return modified;
        }
    }
    

    HashSet

    概述

    HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。主要具有以下的特点:

    • 不保证set的迭代顺序,特别是它不保证该顺序恒久不变

    • 有且只允许一个null元素

    • 不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个private static final Object PRESENT = new Object();

    • 非同步的。如果多 个线程同时访问一个哈希set,而其中至少一个线程修改了该 set,那么它必须保持外部同步。这通常是通过对自然封装该set的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该set进行意外的不同步访问:

    Set s = Collections.synchronizedSet(new HashSet());
    
    • HashSet通过iterator()返回的迭代器是fail-fast的

    类继承实现关系

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
    {
    

    类属性

    //hashMap
        private transient HashMap<E,Object> map;
    
        //HashMap的value
        private static final Object PRESENT = new Object();
    

    构造方法

    public HashSet() {
            map = new HashMap<>();
        }
        
           public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
          public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
            public HashSet(int initialCapacity) {
            map = new HashMap<>(initialCapacity);
        }
    //不对外公开的一个构造方法(默认default修饰),底层构造的是LinkedHashMap,dummy只是一个标示参数,无具体意义。 给LinkedHashSet调用的
            HashSet(int initialCapacity, float loadFactor, boolean dummy) {
            map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }
    

    其他的所有方法都是调用的HashMap的方法。只需要知道HashSet的特点就可以了。

    LinkedHashSet

    特点和HashSet一样。基于LinkedHashMap的双向链表。构造方法都是调用HashSet那个默认的构造方法,创建的是LinkedHashMap。有序,有且只有一个null,不允许重复,线程不安全

  • 相关阅读:
    hdu 1399(水题)
    hdu 1252(BFS)
    sm3算法的简单介绍
    undefined reference to 问题汇总及解决方法 ----- 还有一种问题没有解决(可能是顺序问题)
    OpenSSL之X509系列
    RSA key lengths
    进程间通信(IPC)介绍
    判断主机、网络字节序和互相转换
    整理struct sockaddr和struct sockaddr_in
    valgrind 的使用简介
  • 原文地址:https://www.cnblogs.com/yangk1996/p/12653502.html
Copyright © 2011-2022 走看看