Java 汇合Collection和Map详解

一:汇合由来
咱们要求能在任何时候,任何地点创立任意数量的对象,而这些对象用什么来包容呢?,咱们首先想到了数组,然而数组只能寄存同一类型的数据,而且长度是固定的,故汇合变应运而生
Java汇合类寄存在java.util包中,是一个用来寄存对象的容器。
1.汇合只能寄存对象。比方你存入一个int型数据66放入汇合中,其实它是主动转换成Integer类后存入的,Java中每一种根本数据类型都有对应的援用类型。
2.汇合寄存的都是对象的援用,而非对象自身。所以咱们称汇合中的对象就是汇合中对象的援用。对象自身还是放在堆内存中。
3.汇合能够寄存不同类型,不限数量的数据类型。
二:Java汇合框架

汇合和数组的区别

三:Collection汇合和Iterator迭代器
咱们先来看一看List汇合和Set汇合的父类Collection汇合,以及实现的迭代器的接口
查看Iterator源码次要有三个办法:

public interface Iterator<E> {//判断容器内是否还有可供拜访的元素 boolean hasNext(); //返回迭代器刚越过的元素的援用,返回值是对象Object须要强制转换成本人须要的类型。(泛型)  E next();  //删除迭代器刚越过的元素。  default void remove() {}        }

个别迭代器Iterator 应用:

  List<String> list=new ArrayList<>();        //增加元素        list.add("Rocky");        list.add("Tom");        list.add("Mark");        //list.iterator()结构List的迭代器        Iterator iterator=list.iterator();        //通过迭代器遍历元素        while (iterator.hasNext()){           Object obj= iterator.next();           System.out.println(obj);        }                        //形式二,减少一个删除         List<String> list=new ArrayList<>();        //增加元素        list.add("Rocky");        list.add("Tom");        list.add("Mark");        //list.iterator()结构List的迭代器        Iterator<String> iterator=list.iterator();//Iterator汇合具体实例的String对象        //通过迭代器遍历元素        while (iterator.hasNext()){           String str= iterator.next();           if ("Rocky".equals( str)){               //删除元素               iterator.remove();           }else {               System.out.println(str);           }        }

Collection接口规定了汇合的一些基本操作
查看Collection源码解析:

//Collection接口继承了迭代器的接口public interface Collection<E> extends java.lang.Iterable<E> {//返回汇合的数量public int size();//判断汇合是否为空public boolean isEmpty();//判断汇合是否蕴含某些元素public boolean contains(Object o);//判断汇合是否蕴含某些汇合public boolean containsAll(Collection c);//在汇合开端增加元素public boolean add(E e);//删除该元素,并返回truepublic boolean remove(Object o);//清空集合public void clear();//迭代器汇合专用遍历形式public Iterator iterator();//返回一个蕴含了本类集中所有元素的数组,数组类型为Object[]public  Object[] toArray();public boolean equals(Object o);public int hashCode();}

三:汇合具体实现List
Collection 接口的接口 对象的汇合(单列汇合)

List 接口:元素按进入先后有序保留,可反复       LinkedList 接口实现类, 链表, 插入删除,增删快 没有同步, 线程不平安       ArrayList 接口实现类, 数组, 随机拜访, 增删慢 没有同步, 线程不平安       Vector 接口实现类 数组, 同步, 增删慢 线程平安             Stack 是Vector类的实现类 Set 接口: 仅接管一次,不可反复,并做外部排序       HashSet 应用hash表(数组)存储元素       LinkedHashSet 链表保护元素的插入秩序       TreeSet 底层实现为二叉树,元素排好序


1.ArrayList
ArrayList:底层数据结构是数组,查问快,增删慢,线程不平安,效率高,能够存储反复元素
ArrayList是基于数组实现的List类,它封装了一个动静的增长的、容许再调配的Object[]数组
查看源码:
除了继承Collection接口的办法外

public class ArrayList<E> extends AbstractList<E>        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{//返回指定元素在汇合的第一次呈现的索引 public int indexOf(Object o) {} //返回指定元素在汇合的最初一次呈现的索引 public int lastIndexOf(Object o) {} //获取指定地位的元素 public E get(int index) {}  //批改指定索引地位的元素值,批改为指定值,返回批改前的值 public E set(int index, E element) {} //列表迭代器 public ListIterator<E> listIterator(){}}//截取汇合是[);如subList(1,3)只蕴含1,2前闭后开public List<E> subList(int fromIndex, int toIndex) {}//移除索引对应的元素public E remove(int index);

ArrayList底层实现是数组,是有序的,可反复的,查问快(数组的特点),增删慢
2.LinkedList
LinkedList 底层数据结构是链表,查问慢,增删快,线程不平安,效率高,能够存储反复元素
implements List<E>, Deque<E>。实现List接口,能对它进行队列操作,即能够依据索引来随机拜访汇合中的元素。同时它还实现Deque接口,即能将LinkedList当作双端队列
LinkedList源码解析

public class LinkedList<E>    extends AbstractSequentialList<E>    implements List<E>, Deque<E>, Cloneable, java.io.Serializable{transient int size = 0;//大小 transient Node<E> first;//头节点  transient Node<E> last;//尾节点  //增加头元素public void addFirst(E e)//增加尾元素public void addLast(E e)}//获取头元素 public E getFirst()  //获取尾元素  public E getLast()  //移除头元素  public E removeFirst()  //移除尾元素   public E removeLast()   //入栈,其实就是在头部增加元素   public void push(E e)   //平安的增加操作,在尾部增加    public boolean offer(E e)    //在头部增加    public boolean offerFirst(E e) {        addFirst(e);        return true;    }    //尾部增加    public boolean offerLast(E e) {        addLast(e);        return true;    }    //删除头部    public E pop() {        return removeFirst();    }    public E pollFirst() {    final Node<E> f = first;    return (f == null) ? null : unlinkFirst(f);}public E pollLast() {    final Node<E> l = last;    return (l == null) ? null : unlinkLast(l);}**LinkedList汇合中List接口的实现类。存取有序,有索引,可反复,查问慢,增删快(链表的特点)**   

Vetor
个别应用

//形式一通过Enumeration//这种传统接口已被迭代器取代,尽管Enumeration 还未被遗弃,但在古代代码中曾经被很少应用了。 Vector vector=new Vector();        //增加元素        vector.add("Rocky");        vector.add("Tom");        vector.add("Mark");        Enumeration<String> enumeration=vector.elements();            while (enumeration.hasMoreElements()){            String str= enumeration.nextElement();            System.out.println(str);            }                //形式二,通过迭代器    Vector vector=new Vector();        //增加元素        vector.add("Rocky");        vector.add("Tom");        vector.add("Mark");Iterator<String> iterator=vector.iterator();  //通过迭代器遍历元素     while (iterator.hasNext()){           String str= iterator.next();           if ("Rocky".equals( str)){               //删除元素               iterator.remove();           }else {               System.out.println(str);           }        }

Enumeration接口源码:

//能够看到Enumeration没有删除办法public interface Enumeration<E> {boolean hasMoreElements();//相似于Iterator的hasNext() E nextElement();//相似于迭代器iterator的next();}

Vector与ArrayList相似, 外部同样保护一个数组, Vector是线程平安的. 办法与ArrayList大体一致, 只是加上 synchronized 关键字, 保障线程平安
Vector的源码解析:

public class Vector<E>    extends AbstractList<E>    implements List<E>, RandomAccess, Cloneable, java.io.Serializable{//次要字段 存储的数组protected Object[] elementData;//次要字段 存储元素的个数 protected int elementCount; //扩容时的增加量,大于0减少capacityIncrement否则翻倍  protected int capacityIncrement;     public Vector() {        this(10);//默认是10    }    //初始化时候容量为10    //容量大于0减少为capacityIncrement,否则翻倍     public Vector(int initialCapacity, int capacityIncrement) {        super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        this.elementData = new Object[initialCapacity];        this.capacityIncrement = capacityIncrement;    }}//依据索引获取元素synchronized 用了这个关键词润饰,同步 public synchronized E elementAt(int index) {} //增加汇合  public synchronized boolean addAll(Collection<? extends E> c){} //从index所示意的下标处开始搜寻obj. public synchronized int indexOf(Object o, int index) {}  //从向量尾部开始逆向搜寻obj. public synchronized int lastIndexOf(Object o){}   //删除index所指的中央的对象 public fianl synchronized void removeElementAt(int index)  //将index处的对象设置成obj,原来的对象将被笼罩。 public final synchronized void setElementAt(Object obj,int index)  //获取向量对象中的首个objpublic final synchornized firstElement() 

Vector是有序的,能够反复的。

四:汇合的具体实现Set类
1.HashSet
Hashset底层是hashMap保护数据的表
因为数组的索引是间断的而且数组的长度是固定的,无奈自在减少数组的长度。而HashSet就不一样了,HashCode表用每个元素的hashCode值来计算其存储地位,从而能够自在减少HashCode的长度,并依据元素的hashCode值来拜访元素。而不必一个个遍历索引去拜访,这就是它比数组快的起因。

个别应用

//创立汇合 Set<String> name=new HashSet<>(); //增加元素        name.add("Rocky");        name.add("Jack");        name.add("Tom");         //name.add("Jack");        //增加雷同的元素输入后果没变        //构建迭代器        Iterator<String> iterator1=name.iterator();        while (iterator1.hasNext()){            String s=iterator1.next();            System.out.println(s);        }    }        //后果System.out: RockySystem.out: TomSystem.out: Jack

Hashset的汇合详解

public class HashSet<E>    extends AbstractSet<E>    implements Set<E>, Cloneable, java.io.Serializable{ private transient HashMap<E,Object> map; //HashSet这个类实现了Set汇合,理论为一个HashMap的实例 //无参数的构造函数,此构造函数创立一个大小为16的容器,加载因子为0.75   public HashSet() {        map = new HashMap<>();    }    //是否蕴含对象      public boolean contains(Object o) {        return map.containsKey(o);    }    //增加元素     public boolean add(E e) {        return map.put(e, PRESENT)==null;    }    //删除元素    public boolean remove(Object o)    //从此 set 中移除所有元素。     public void clear() {        map.clear();    }}

HashSet:无序,不能反复
2.LinkedHashSet
HashSet还有一个子类LinkedHashSet,LinkedHashSet汇合也是依据元素的hashCode值来决定元素的存储地位,但它同时应用链表保护元素的秩序,这样使得元素看起来是以插入的程序保留的,也就是说当遍历汇合LinkedHashSet汇合里的元素时,汇合将会按元素的增加程序来拜访汇合里的元素。
输入汇合里的元素时,元素程序总是与增加程序统一。然而LinkedHashSet仍然是HashSet,因而它不容许汇合反复
下面说的的就是输入后果是和增加程序是统一的,然而set一样不能有反复的元素(有序,不能反复
LinkedHashSet源码解析:

public class LinkedHashSet<E>    extends HashSet<E>    implements Set<E>, Cloneable, java.io.Serializable {    //构造方法,默认是16容量,加载因子0.75 public LinkedHashSet() {        super(16, .75f, true);    }    应为是Hashset子类,就不多余赘述了,就是有序}

3.TreeSet
TreeSet是SortedSet接口的实现类,TreeSet能够确保汇合元素处于排序状态。
TreeSet外部实现的是红黑树,默认整形排序为从小到大。
个别应用

        TreeSet<Integer> name=new TreeSet<>();        name.add(12);        name.add(11);        name.add(16);        name.add(15);        name.add(9);        Iterator<Integer> iterator1=name.iterator();        while (iterator1.hasNext()){            Integer s=iterator1.next();            System.out.println(s);        }        //返回在这个汇合中小于或者等于给定元素的最大元素(<= 给定的最大元素)        System.out.println("Floor value for 12: "+name.floor(12));        //返回在这个汇合中大于或者等于给定元素的最小元素(>=给定元素的最小元素)        System.out.println("Ceiling value for 12: "+name.ceiling(12));        //返回汇合中的开始一个元素        System.out.println("First value : "+name.first());        //返回汇合中的最初一个元素        System.out.println("Last value: "+name.last());        //返回指定元素12之后的元素。        System.out.println("High value for 13: "+name.higher(12));        //返回指定元素12之前的元素。        System.out.println("Low value for 13: "+name.lower(12));        //后果System.out: 9System.out: 11System.out: 12System.out: 15System.out: 16System.out: Floor value for 12: 12System.out: Ceiling value for 12: 12System.out: First value : 9System.out: Last value: 16System.out: High value for 12: 15System.out: Low value for 12: 11//下面输入的数据曾经是有程序的了,什么起因了//TreeSet会调用汇合元素的compareTo(Objec obj)办法来比拟元素之间的大小关系,而后将汇合元素按升序排列,这就是天然排序

源码解析

//实现的NavigableSet,public interface NavigableSet<E> extends SortedSet<E> 继承与于SortedSet//SortSet接口,次要提供了一些排序办法// Comparator<? super E> comparator();// SortedSet<E> subSet(E fromElement, E toElement);返回此Set的子集合,含头不含尾 //SortedSet<E> headSet(E toElement);返回此Set的子集,由小于toElement的元素组成; //SortedSet<E> tailSet(E fromElement);返回此Set的子集,由大于fromElement的元素组成; //E last();返回汇合中的最初一个元素; //E first();返回汇合中的第一个元素;public class TreeSet<E> extends AbstractSet<E>    implements NavigableSet<E>, Cloneable, java.io.Serializable{//蕴含什么元素 public boolean contains(Object o) {        return m.containsKey(o);    }    //增加元素     public boolean add(E e) {        return m.put(e, PRESENT)==null;    }    //移除元素     public boolean remove(Object o) {        return m.remove(o)==PRESENT;    }    //还有就是SortSet接口的实现办法     public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,                                  E toElement,   boolean toInclusive)       // 返回汇合中的最初一个元素                                 public E last() {        return m.lastKey();    }    //返回指定元素之前的元素。     public E lower(E e) {        return m.lowerKey(e);    }    //返回在这个汇合中小于或者等于给定元素的最大元素(<= 给定的最大元素)    public E floor(E e) {        return m.floorKey(e);    }    //返回在这个汇合中大于或者等于给定元素的最小元素(>=给定元素的最小元素)     public E ceiling(E e) {        return m.ceilingKey(e);    }    //返回指定元素之后的元素。     public E higher(E e) {        return m.higherKey(e);    }}

五:Map汇合
Map中的汇合,元素是成对存在的(了解为夫妻)。每个元素由键与值两局部组成,通过键能够找对所对应的值。
HashMap<K,V>:存储数据采纳的哈希表构造,元素的存取程序不能保障统一。因为要保障键的惟一、不反复,须要重写键的hashCode()办法、equals()办法。
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采纳的哈希表构造+链表构造。通过链表构造能够保障元素的存取程序统一;通过哈希表构造能够保障的键的惟一、不反复,须要重写键的hashCode()办法、equals()办法。
TreeMap:非线程平安基于红黑树实现。TreeMap没有调优选项,因为该树总处于均衡状态。
个别应用:

//创立Map对象        //数据采纳Hash表实现        HashMap<String, String> map = new HashMap<>();        //给map增加元素        map.put("num:One","Java");         //map.put("num:One","Java");即便我增加一个反复元素,后果一样        map.put("num:Two","C");        map.put("num:Three","Python");        map.put("num:Four","C++");        System.out.println(map);        //后果       System.out: {num:One=Java, num:Four=C++, num:Two=C, num:Three=Python}        //存取程序不统一,不反复

剖析Map的源码,解析Map的办法

public interface Map<K, V> {//返回该Map外面的键值对的个数public int size();//查问map是否为空,如果空则返回truepublic boolean isEmpty();//查问Map中是否蕴含指定的key,如果蕴含则返回truepublic boolean containsKey(Object obj);//查问Map中是否蕴含指定的Value,如果蕴含则返回truepublic boolean containsValue(Object obj);//返回指定key所对应的value,如果map中不蕴含key则返回nullpublic V get(Object key)//增加一个键值对,如果曾经有了雷同的key值,则新的键值对笼罩旧的键值对public V put(Object key,Object value)//删除指定key所对应的键值对,返回能够关联的value,如果key不存在,返回nullpublic V remove(Object key)//将指定Map中键值对复制到Map中public void putAll(Map m)//革除所有的键值对public void clear();//拿到所有的key的Set汇合Set<K> keySet();//返回该Map里所有的Value组成的CollectionCollection values();//这个拿到了键值对的 Entry<K, V>汇合Set<Map.Entry<K, V>> entrySet();//外部类接口public static interface Entry<K, V> {//返回该Entry里蕴含的key值public K getKey();/返回该Entry里蕴含的value值public V getValue();/设置该Entry里蕴含的value值,并返回新的value值public V setValue(V value);}}

应用

创立Map对象        //数据采纳Hash表实现        HashMap<String, String> map = new HashMap<>();        //给map增加元素        map.put("num:One","Java");        map.put("num:One","Java");        map.put("num:Two","C");        map.put("num:Three","Python");        map.put("num:Four","C++");        System.out.println(map);        //第一种:广泛应用,二次取值        System.out.println("通过Map.keySet遍历key和value:");        for (String key : map.keySet()) {            System.out.println("key= "+ key + " and value= " + map.get(key));        }        //第二种,通过外部类Entry        System.out.println("通过Map.entrySet应用iterator遍历key和value:");        //map.entrySet()拿到Set汇合Entry<String, String>        Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();        while (it.hasNext()) {            Map.Entry<String, String> entry = it.next();            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());        }        //第三种:举荐,尤其是容量大时,map.entrySet()拿到Set(Entry<String, String> )汇合,元素是Entry<String, String> 遍历并打印出key和value        System.out.println("通过Map.entrySet遍历key和value");        for (Map.Entry<String, String> entry : map.entrySet()) {            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());        }        //第四种通过values拿到所有的value汇合遍历所有的value值打印        System.out.println("通过Map.values()遍历所有的value,但不能遍历key");        for (String v : map.values()) {            System.out.println("value= " + v);        }                //后果System.out: {num:One=Java, num:Four=C++, num:Two=C, num:Three=Python}System.out: 通过Map.keySet遍历key和value:System.out: key= num:One and value= JavaSystem.out: key= num:Four and value= C++System.out: key= num:Two and value= CSystem.out: key= num:Three and value= PythonSystem.out: 通过Map.entrySet应用iterator遍历key和value:System.out: key= num:One and value= JavaSystem.out: key= num:Four and value= C++System.out: key= num:Two and value= CSystem.out: key= num:Three and value= PythonSystem.out: 通过Map.entrySet遍历key和valueSystem.out: key= num:One and value= JavaSystem.out: key= num:Four and value= C++System.out: key= num:Two and value= CSystem.out: key= num:Three and value= PythonSystem.out: 通过Map.values()遍历所有的value,但不能遍历keySystem.out: value= JavaSystem.out: value= C++System.out: value= CSystem.out: value= Python

1.HashMap
基于哈希表实现。应用HashMap要求增加的键类明确定义了hashCode()和equals()[能够重写hashCode()和equals()],为了优化HashMap空间的应用,您能够调优初始容量和负载因子。
LinkedHashMap是HashMap的惟一子类

public class LinkedHashMap<K,V>    extends HashMap<K,V>    implements Map<K,V>{//默认对map输出和输入是有序的//HashMap和双向链表合二为一即是LinkedHashMap。所谓LinkedHashMap,其落脚点在HashMap//因为有双向循环列表,所以LinkedHashMap可能记录插入元素的程序}

HashMap和HashTable的比拟:

2.TreeMap
非线程平安基于红黑树实现。TreeMap没有调优选项,因为该树总处于均衡状态。

TreeMap源码剖析

//TreeMap这里实现的NavigableMap,public interface NavigableMap<K, V> extends java.util.SortedMap<K,V> //SortedMap是一个排序类和SortedSet相似// SortedMap<K,V> subMap(K fromKey, K toKey);// SortedMap<K,V> headMap(K toKey);// SortedMap<K,V> tailMap(K fromKey);// K firstKey();//返回最小key,如果为空,则返回null// K lastKey();//返回最大key,如果为空,则返回null// Set<K> keySet();//  Collection<V> values();//Set<Map.Entry<K, V>> entrySet();public class TreeMap<K,V>    extends AbstractMap<K,V>    implements NavigableMap<K,V>, Cloneable, java.io.Serializable{//实用于按天然程序或自定义程序遍历键(key)。//蕴含key值,是返回true  public boolean containsKey(Object key)  ......    //返回具备最小键值(大于或等于指定键)的键值对,如果没有这样的键,则返回null。(>=指定键的最小键的汇合)      public Map.Entry<K,V> ceilingEntry(K key) {}        public K ceilingKey(K key){}        //返回与小于或等于给定键元素(key_ele)的最大键元素链接的键值对(如果存在)。(<=指定键的最大键值的键值对)      public Map.Entry<K,V> floorEntry(K key) {}         public K floorKey(K key) {}         //返回与严格大于给定键的最小键关联的键-值映射,如果没有这样的键,则返回null。        public Map.Entry<K,V> higherEntry(K key) {}        public K higherKey(K key){}        //返回严格小于给定键(作为参数传递)的最大键        public Map.Entry<K,V> lowerEntry(K key) {}         public K lowerKey(K key){}}

下面是汇合的全部内容
汇合Collection和Map用到了数据结构有数组,链表,Hash表,红黑树等

结尾:深刻学习才是无效学习