关于android:Java-集合Collection和Map详解

41次阅读

共计 13820 个字符,预计需要花费 35 分钟才能阅读完成。

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);
// 删除该元素,并返回 true
public 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) 
 // 获取向量对象中的首个 obj
public 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: Rocky
System.out: Tom
System.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: 9
System.out: 11
System.out: 12
System.out: 15
System.out: 16
System.out: Floor value for 12: 12
System.out: Ceiling value for 12: 12
System.out: First value : 9
System.out: Last value: 16
System.out: High value for 12: 15
System.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 是否为空,如果空则返回 true
public boolean isEmpty();
// 查问 Map 中是否蕴含指定的 key, 如果蕴含则返回 true
public boolean containsKey(Object obj);
// 查问 Map 中是否蕴含指定的 Value,如果蕴含则返回 true
public boolean containsValue(Object obj);
// 返回指定 key 所对应的 value, 如果 map 中不蕴含 key 则返回 null
public V get(Object key)
// 增加一个键值对,如果曾经有了雷同的 key 值,则新的键值对笼罩旧的键值对
public V put(Object key,Object value)
// 删除指定 key 所对应的键值对,返回能够关联的 value, 如果 key 不存在,返回 null
public V remove(Object key)
// 将指定 Map 中键值对复制到 Map 中
public void putAll(Map m)
// 革除所有的键值对
public void clear();
// 拿到所有的 key 的 Set 汇合
Set<K> keySet();
// 返回该 Map 里所有的 Value 组成的 Collection
Collection 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= Java
System.out: key= num:Four and value= C++
System.out: key= num:Two and value= C
System.out: key= num:Three and value= Python

System.out: 通过 Map.entrySet 应用 iterator 遍历 key 和 value:System.out: key= num:One and value= Java
System.out: key= num:Four and value= C++
System.out: key= num:Two and value= C
System.out: key= num:Three and value= Python

System.out: 通过 Map.entrySet 遍历 key 和 value
System.out: key= num:One and value= Java
System.out: key= num:Four and value= C++
System.out: key= num:Two and value= C
System.out: key= num:Three and value= Python

System.out: 通过 Map.values()遍历所有的 value,但不能遍历 key
System.out: value= Java
System.out: value= C++
System.out: value= C
System.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 表,红黑树等

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

正文完
 0