Java集合

欢迎光临我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后台使用Spring Boot

前言

集合只能存储对象,存放的是多个对象的引用,对象本身还是放在堆内存中。


Collections和Arrays工具类:
	两个工具类分别操作集合和数组,可以进行常用的排序,合并等操作。


TreeMap和TreeSet:
	主要是基于红黑树实现的两个数据结构,可以保证key序列是有序的。

HashMap和HashSet:
	基于哈希表实现,支持快速查找。


ArrayList(有序列表,允许存放重复的元素,允许使用null元素)

接口:
	List
实现类: 
	LinkedList,Vector,ArrayList:
		ArrayList:数组实现,查询快,增删慢,轻量级(线程不安全)
		LinkedList:双向链表实现,增删快,查询慢,轻量级(线程不安全)
		Vector:数组实现,重量级(线程安全、使用少)


ArrayList是实现List接口的动态数组。

同步访问:List list = Collections.synchronizedList(new ArrayList(...));


ArrayList:
	继承:
		AbstractList抽象父类
	实现:
		List接口(规定了List的操作规范)
		RandomAccess(可随机访问)
		Cloneable(可拷贝)
		Serializable(可序列化)


ArrayList:
	优点:
		get(int index) set(int index, E element)与顺序添加( add(E e) )非常快。时间复杂度O(1)
	缺点:
		插入删除( add(int index, E element) 和 remove(int index) )非常慢,因为涉及元素复制。时间复杂度O(n)


public class ArrayList<E>
	extends AbstractList<E>
	implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector大部分方法都使用了synchronized修饰符,所以他是线层安全的集合类。

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

public class Stack<E> extends Vector<E>

ArrayList详解

LinkedList(有序列表,允许存放重复的元素,允许使用null元素)

LinkedList是采用双向循环链表实现的:
	利用LinkedList实现栈(stack)、队列(queue)、双向队列(double-ended queue)。
	它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等。


public class LinkedList<E>
	extends AbstractSequentialList<E>
	implements List<E>, Deque<E>, Cloneable, java.io.Serializable


LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList差。

LinkedList详解

Set(不允许存放重复的元素,允许使用null元素)

接口:Set
实现类:HashSet (无序,查找时间复杂度为O(1) )、LinkedHashSet(有序)

Set的子接口:SortedSet
实现类:TreeSet (排序, 查找时间复杂度O(logN) )


HashSet常用方法:
	public boolean contains(Object o);	//如果set包含指定元素,返回true


HashSet需要同时通过equals和HashCode来判断两个元素是否相等:
	具体规则是,如果两个元素通过equals为true,并且两个元素的hashCode相等,则这两个元素相等(即重复)。


LinkedHashSet本质上也是从LinkedHashMap而来:
	LinkedHashSet的所有方法都继承自HashSet, 而它能维持元素的插入顺序的性质则继承自LinkedHashMap。


TreeSet(只允许存入同一类的元素):
	TreeSet的排序分两种类型,一种是自然排序,另一种是定制排序:
	
	自然排序(在元素中写排序规则):
		TreeSet 会调用compareTo()方法比较元素大小,然后按升序排序。所以自然排序中的元素对象,都必须实现了Comparable接口
	定制排序(在集合中写排序规则)
		TreeSet 还有一种排序就是定制排序,定制排序时候,需要关联一个 Comparator对象。


总结:
	HashSet 的元素存放顺序和我们添加进去时候的顺序没有任何关系。
	LinkedHashSet 则保持元素的添加顺序。
	TreeSet 则是对我们的Set中的元素进行排序存放。

HashSet详解

Map(关键字唯一,允许使用null元素)

实现类:
	HashMap、TreeMap、LinkedHashMap、Hashtable

HashMap:
	键值对,key不能重复,但是value可以重复,允许null的键或值。

Hashtable:
	线程安全的,不允许null的键或值。

Properties:
	key和value都是String类型,用来读配置文件。

TreeMap:
	对key排好序的Map。key要实现Comparable接口或TreeMap有自己的构造器。

LinkedHashMap: 
	此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。存储的数据是有序的。


HashMap实现原理:散列
	如果负载因子0.75,当散列表中已经有75%位置已经放满,那么将进行再散列。
	负载因子越高(越接近1.0),内存的使用效率越高,元素的寻找时间越长。
	负载因子越低(越接近0.0),元素的寻找时间越短,内存浪费越多。


Map集合比较:
	HashMap 无序。
	LinkedHashMap 保留了键值对的存入顺序。
	TreeMap 则是对Map中的元素进行排序。
	HashMap 和 LinkedHashMap 存储数据的速度比直接使用TreeMap 要快,存取效率要高。
	注意:TreeMap中是根据键(Key)进行排序的。
		而如果我们要使用TreeMap来进行正常的排序的话,Key中存放的对象必须实现Comparable接口。


Map常用方法:
	boolean containsKey(Object key) :判断Map中是否存在某键(key)
	boolean containsValue(Object value) :判断Map中是否存在某值(value) 
	public Set<K> keySet() :返回所有的键(key),并使用Set容器存放
	public Collection<V> values() :返回所有的值(Value),并使用Collection存放
	public Set<Map.Entry<K, V>> entrySet(); :返回一个实现 Map.Entry 接口的元素 Set

HashMap详解

Queue

public interface Queue<E> extends Collection<E> {}


PriorityQueue:底层用数组实现堆的结构

public class PriorityQueue<E>
	extends AbstractQueue<E>
	implements java.io.Serializable

PriorityQueue不是一个线程安全的类:
	如果要在多线程环境下使用,可以使用 PriorityBlockingQueue 这个优先阻塞队列。
	其中add、poll、remove方法都使用 ReentrantLock 锁来保持同步,take() 方法中如果元素为空,则会一直保持阻塞。

Deque

public interface Deque<E> extends Queue<E> {}


ArrayDeque:底层使用循环数组实现双向队列

public class ArrayDeque<E>
	extends AbstractCollection<E>
	implements Deque<E>, Cloneable, Serializable {

    transient Object[] elements;

    transient int head;

    transient int tail;
}

Iterator

Iterator iterator = list.iterator();
while(iterator.hasNext()){
	String string = iterator.next();
	do something;
}

public interface Iterator<E> {
  boolean hasNext();
  E next();
  default void remove() {throw new UnsupportedOperationException("remove");}
}

public class ArrayList<E> {
	public Iterator<E> iterator() {return new Itr();}
	private class Itr implements Iterator<E> {
		int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
	}
}

迭代器模式

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。


// 抽象迭代器
interface Iteratoring {
    public boolean hasNext();

    public Object next();
}

//具体迭代器
class ConcreteIterator implements Iteratoring {

    private ArrayList<Object> li;

    public ConcreteIterator(ArrayList<Object> li) {
        this.li = li;
    }

    int count = 0;

    @Override
    public boolean hasNext() {
        if (count < li.size()) {
            return true;
        }
        return false;
    }

    @Override
    public Object next() {
        if (hasNext()) {
            return li.get(count++);
        }
        return null;
    }
}

//抽象聚合
interface Aggregate {
    public void add(Object obj);

    public void remove(Object obj);

    public Iteratoring getIterator();
}

//具体聚合
class ConcreteAggregate implements Aggregate {

    private ArrayList arr = new ArrayList();

    @Override
    public void add(Object obj) {
        arr.add(obj);
    }

    @Override
    public void remove(Object obj) {
        arr.remove(obj);
    }

    @Override
    public Iteratoring getIterator() {
        return new ConcreteIterator(arr);
    }
}

Comparable(内比较器,耦合强) 和 Comparator(外比较器)

public interface Comparable<T> {
	public int compareTo(T o);	//自然比较方法
}

public class Girl implements Comparable<Object> {	//可以用Collections.sort() 或者 Arrays.sort() 进行排序
    public int compareTo(Object o) {
        Girl g = (Girl)o;
        return this.age - g.getAge();
    }
}


public interface Comparator<T> {
	int compare(T o1, T o2);
	boolean equals(Object obj);
	default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }
}


Comparator<User> byName = (User o1, User o2) -> o1.getName().compareTo(o2.getName());

list.sort((User o1,User o2) -> o1.getAge() - o2.getAge());

Fail-Fast 机制

对应非线程安全的数据结构,使用迭代器在发生线程不安全的操作时会报错。
	
实现通过 modCount 域(修改次数),对ArrayList 内容的修改都将增加这个值,
那么在迭代器初始化过程中会将这个值赋给迭代器的 expectedModCount。
在迭代过程中,判断 modCount 跟 expectedModCount 是否相等,如果不相等就表示已经有其他线程修改了 ArrayList。

因此,遍历那些非线程安全的数据结构时,尽量使用迭代器

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

asList() 与 subList() 的缺陷

8个基本类型是无法作为asList的参数的,要想作为泛型参数就必须使用其所对应的包装类型。

asList产生的列表不可操作。


subList()返回的只是原列表的一个视图,它所有的操作最终都会作用在原列表上。

对于子列表视图,它是动态生成的,生成之后就不要操作原列表了,否则必然都导致视图的不稳定而抛出异常。
最好的办法就是将原列表设置为只读状态,要操作就操作子列表。

	删除100-200位置处的数据:
		list.subList(100, 200).clear();
posted @ 2019-11-06 13:42  LittleDonkey  阅读(183)  评论(0编辑  收藏  举报