• JAVA总结集合


    1、集合树状图

    Collection:最基本的集合接口

      ----List:有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问

        ----ArrayList:异步

        ----LinkedList:实现了List和Queue的双接口

        ----Vector:同步

          ----Stack:后进先出,同步

      ----Queue:先入先出(FIFO)数据结构的集合

        ----LinkedList:实现了List和Queue的双接口

      ----Set:无序集合,集合中的元素不可以重复,最多有一个null元素

        ----EnumSet:枚举类型专用,单一枚举类型,无null元素,异步

        ----SortedSet:继承了Set接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序

          ----TreeSet:实现了SortedSet接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeSet的自然排序方式)。(Tips:Set内部源码仍以Map为基础,是value为空对象的Key集合)

        ----HashSet:异步,最多有一个null元素

          ----LinkedHashSet:继承HashSet,调用了 LinkedHashMap中记录插入元素顺序的recordAccess()方法。

    MAP:保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value

      ----HashMap:异步,允许null,即null value和null key

        ----WeakHashMap:对key实行“弱引用”,如果一个key不再被外部所引用,该key可以被GC回收

      ----Hashtable:同步,不允许null

      ----SortedMap:继承了Map接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序

          ----TreeMap:实现了SortedMap接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeMap的自然排序方式)

    2、集合统计信息

    对于Set、List和Map三种集合,最常用的实现类分别是HashSet、ArrayList和HashMap三个实现类;

    Vector、HashTable、Properties和Stack是同步类,所以它们是线程安全的,可以在多线程环境下使用;

    ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问;

    3、集合遍历

    Iterator(迭代器) :hasNext()  next()  remove()

    当前遍历的集合元素被更改的时候,会抛出ConcurrentModificationException,避免报错CopyOnWriteArrayList;(Enumeration不会,不安全)

    for(for循环):

    一:for(Iterator iterator = list.iterator();iterator.hasNext();)

    二:Iterator iterator = list.iterator();   while(iterator.hasNext()){ 

    三:for (Object object : list) {(从JDK1.5开始出现的语法,相当于 while(iterator.hasNext(),所以这里的for循环内部还是迭代器方式遍历)

    四: for (int i = 0 ;i<list.size();i++) {  

    4、原理

    一、Hashtable、HashMap、HashSet的实现原理:

    底层数据结构是哈希表;

    首先判断hashCode()值是否相同

    是:继续执行equals(),看其返回值

      是true:说明元素重复,不添加

      是false:就直接添加到集合

    否:就直接添加到集合

    最终:自动生成hashCode()和equals()即可;

     

    二、线程安全:Hashtable和ConcurrentHashMap

    Hashtable:synchronized是针对整张Hash表的,即每次锁住整张表让线程独占;

    ConcurrentHashMap:锁分离,使用了多个锁来控制对hash表的不同部分(段Segment);但size()和containsValue()等方法依然是跨段对整个表进行加锁(按顺序锁定所有段);ConcurrentHashMap的迭代器为弱一致性,即在遍历并遇到修改时会复制数据进行遍历,遍历结束再将迭代器指针指向新数据。

     

     

    各种集合的原理详解---jdk源码

    Arraylist    LinkList  HashMap  HashSet

    1.ArrayList

    1  private transient Object[] elementData;
    2  private int size;
     1 public ArrayList(int paramInt)
     2   {
     3     if (paramInt < 0)
     4       throw new IllegalArgumentException("Illegal Capacity: " +      paramInt);
     6        this.elementData = new Object[paramInt];
     7   }
     8 
     9   public ArrayList()
    10   {
    11       this(10);
    12   }

    ArrayList构造方法,支持预定长度,使用类中的全局变量Object类型的数组,进行数据的保存。

    2.LinkList  

    1 private transient Entry<E> header;
    2 private transient int size;
     1   public LinkedList()
     2   {
     3     this.header = new Entry(null, null, null);
     4     this.size = 0;
     5 
     6     this.header.next = (this.header.previous = this.header);
     7   }
     8 
     9   public LinkedList(Collection<? extends E> paramCollection)
    10   {
    11     addAll(paramCollection);
    12   }

    LinkList  构造方法,支持预设值一个集合,方法addAll为for循环创建并增加集合数据。

     1 private static class Entry<E>
     2   {
     3     E element;
     4     Entry<E> next;
     5     Entry<E> previous;
     6 
     7     Entry(E paramE, Entry<E> paramEntry1, Entry<E> paramEntry2)
     8     {
     9       this.element = paramE;
    10       this.next = paramEntry1;
    11       this.previous = paramEntry2;
    12     }
    13   }

    LinkList  中的Entry 为静态内部私有类,包括前后指针和数据。

    3.HashMap 存储/读取数据原理:

    //定义
    //private transient Set<Map.Entry<K, V>> entrySet;


    public HashMap(int paramInt) { this(paramInt, 0.75F); } public HashMap() { this.entrySet = null; this.loadFactor = 0.75F; this.threshold = 12; this.table = new Entry[16]; init(); } public HashMap(Map<? extends K, ? extends V> paramMap) { this(Math.max((int)(paramMap.size() / 0.75F) + 1, 16), 0.75F); putAllForCreate(paramMap); }

    HashMap在无参数下,初始化entry为16(2的指数),仅保存12个元素;以16为基础翻倍扩容,存储数据以12为基础翻倍增加;

     1 public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
     2     private static final int MINIMUM_CAPACITY = 4;
     3 ...
     4     transient HashMapEntry<K, V>[] table;
     5 ...
     6     private static final Entry[] EMPTY_TABLE
     7             = new HashMapEntry[MINIMUM_CAPACITY >>> 1];
     8   ...       
     9    @Override public V put(K key, V value) {
    10         if (key == null) {
    11             return putValueForNullKey(value);
    12         }
    13 
    14         int hash = Collections.secondaryHash(key);
    15         HashMapEntry<K, V>[] tab = table;
    16         int index = hash & (tab.length - 1);
    17         for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
    18             if (e.hash == hash && key.equals(e.key)) {
    19                 preModify(e);
    20                 V oldValue = e.value;
    21                 e.value = value;
    22                 return oldValue;
    23             }
    24         }
    25 
    26         // No entry for (non-null) key is present; create one
    27         modCount++;
    28         if (size++ > threshold) {
    29             tab = doubleCapacity();
    30             index = hash & (tab.length - 1);
    31         }
    32         addNewEntry(key, value, hash, index);
    33         return null;
    34     }
    35     ...
    36         public V get(Object key) {
    37         if (key == null) {
    38             HashMapEntry<K, V> e = entryForNullKey;
    39             return e == null ? null : e.value;
    40         }
    41 
    42         int hash = Collections.secondaryHash(key);
    43         HashMapEntry<K, V>[] tab = table;
    44         for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
    45                 e != null; e = e.next) {
    46             K eKey = e.key;
    47             if (eKey == key || (e.hash == hash && key.equals(eKey))) {
    48                 return e.value;
    49             }
    50         }
    51         return null;
    52         }
    53     ...
    54     }

     分析下put方法的实现:

    •     if (key == null) {

                     return putValueForNullKey(value);

                }

            首先判断是否为null,如果为null则特殊处理;

    •     2、int hash = Collections.secondaryHash(key);

            获取Key的二级hash值,其中Collections.secondaryHash方法的实现就是把Key的hashcode值做一定改变;

    •     int index = hash & (tab.length - 1);

         通过刚才计算的hash值来获取该key应该存放在数组的下标位置,也就是获取该数据应该存储在table数组的哪个位置;

    •     for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {

                           if (e.hash == hash && key.equals(e.key)) {

                                      preModify(e);

                                      V oldValue = e.value;

                                     e.value = value;

                                   return oldValue;

                }

           }

        如果已经有该key存在了,则覆盖这个key的值value。

        注意这里的判断:因为只有两个对象的hashcode值相等并且两个对象用equals判断返回true时,才去覆盖原有的值;

    •   if (size++ > threshold) {

                          tab = doubleCapacity();

                          index = hash & (tab.length - 1);

              }

            addNewEntry(key, value, hash, index);

            如果该key不存在,或者发生碰撞的对象不是一个对象时,则需要把它存储下来。首先如果存储数量已经大于数组大小,则把数组双倍扩大。然后再把键值对保存到数组中。

            注意这里保存的时候,如果数组存储位置原本就存在键值对,那么则把新的键值对对象保存到旧的键值对 对象next变量中,构成链表。

    • hashMap是table和entry的组合,他的扩容机制,保证table与entry比例均衡,对table的查询与entry的修改的优点进行均衡采用。

    4.HashSet

      private transient HashMap<E, Object> map;
      private static final Object PRESENT = new Object();
    public HashSet()
      {
        this.map = new HashMap();
      }
      public boolean add(E paramE)
      {
        return (this.map.put(paramE, PRESENT) == null);
      }

    由源码可见,HashSet用的就是HashMap实现的,其类中定义一个final状态的Object对象,作为每个数据元素的value,HashSet仅仅使用HashMap的key进行数据的保存,其remove等方法均调用HashMap的方法实现。

  • 相关阅读:
    无监督学习在反欺诈中的应用
    Java中Object对象方法
    ambari下httpfs安装
    深入理解spark-rdd详解
    Tensorflow实践Basic Classification
    深入理解spark-两种调度模式FIFO,FAIR模式
    深入理解spark-taskScheduler,schedulerBackend源码分析
    js模仿页面点击
    记一次请求走私学习
    十种常见的报错注入
  • 原文地址:https://www.cnblogs.com/huasky/p/7509697.html
Copyright © 2020-2023  润新知