java集合

来源:互联网 发布:淘宝店主风调色滤镜 编辑:程序博客网 时间:2024/06/05 20:02

1. 数组和集合

数组只能存储基本数据类型,并且长度固定,不适合存储数量未知的.
集合可以存储对象,容量可以扩展.

2. Collection结构

这里写图片描述
集合接口方法:

public interface Collection<E> extends Iterable<E> {    boolean isEmpty();    boolean contains(Object o);    Iterator<E> iterator();    Object[] toArray();    <T> T[] toArray(T[] a);    boolean add(E e);    boolean remove(Object o);    boolean containsAll(Collection<?> c);    boolean addAll(Collection<? extends E> c);    boolean removeAll(Collection<?> c);    boolean retainAll(Collection<?> c);    void clear();    boolean equals(Object o);    int hashCode();}

2.1 Set

Set特点就是无序,不能重复,就是简单的把数据放到集合当中去.
以HashSet来看,从其中的构造函数可以看到,还是创建了一个HashMap对象来存储的

public HashSet() {    map = new HashMap<E,Object>();    }

在调用Set实现类的add()方法的时候,会调用HashMap的put()方法

public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        int hash = hash(key.hashCode());        int i = indexFor(hash, table.length);        for (Entry<K,V> e = table[i]; e != null; e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }

从上述put的代码中可以看到,首先获取key值(键值)对应的hash值,算法如下:

static int hash(int h) {        // This function ensures that hashCodes that differ only by        // constant multiples at each bit position have a bounded        // number of collisions (approximately 8 at default load factor).        h ^= (h >>> 20) ^ (h >>> 12);        return h ^ (h >>> 7) ^ (h >>> 4);    }

如果哈希值一致,则不放入hashcode录入,如果一致,然后通过调用equals()方法,如果一致,则同样不放入hashcode录入,如果不一致,则放入set中.

Hash哈希算法的意义在于提供了一种快速存取数据的方法,它用一种算法建立键值与真实值之间的对应关系。散列表又称为哈希表。散列表算法的基本思想是:以结点的关键字为自变量,通过一定的函数关系(散列函数)计算出对应的函数值,以这个值作为该结点存储在散列表中地址。
当散列表中的元素存放太满,就必须进行再散列,将产生一个新的散列表,所有元素存放到新的散列表中,原先的散列表将被删除。在Java语言中,通过负载因子(load factor)来决定何时对散列表进行再散列。例如:如果负载因子0.75,当散列表中已经有75%位置已经放满,那么将进行再散列。
负载因子越高(越接近1.0),内存的使用效率越高,元素的寻找时间越长。负载因子越低(越接近0.0),元素的寻找时间越短,内存浪费越多.

LinkedHashSet有HashSet的所有特性,这个是保证put数据的有一定插入的次序.
TreeSet是有序的,TreeSet实现了SortedSet接口,TreeSet中元素将按照升序排列,缺省是按照自然顺序进行排列,意味着TreeSet中元素要实现Comparable接口,我们可以在构造TreeSet对象时,传递实现了Comparator接口的比较器对象.

总之,HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet.

2.2 List

List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢.

ArrayList是有序的,并且可以存储相同的数据,列出list的add()方法

public boolean add(E e) {    ensureCapacity(size + 1);  // Increments modCount!!    elementData[size++] = e;    return true;    }
private transient Object[] elementData;

集合List中底层还是使用数组的形式,只不过数组的长度是可变的,可以扩容的.

LinkedList是采用链表的结构,每个元素存放着前一个元素和后一个元素的指针地址.

ArrayList查询速度快,尾部插入和删除也比较快,一般的删除和插入比较慢
LinkedList删除和插入比较快,但是查询比较慢.

2.3. Map

map并没有实现Collection接口,但是它也属于集合类中的元素,map的键是唯一的,值是可以重复的.

实现类:HashMap、Hashtable、LinkedHashMap和TreeMap

2.3.1 HashMap

HashMap是最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以HashMap最多只允许一条记录的键为Null,允许多条记录的值为Null,是非同步的

2.3.2 Hashtable

Hashtable与HashMap类似,是HashMap的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。

2.3.3 ConcurrentHashMap

线程安全,并且锁分离。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

2.3.4 LinkedHashMap

LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候会比HashMap慢,有HashMap的全部特性。

2.3.5 TreeMap

TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。不允许key值为空,非同步的;

0 0