Java集合学习笔记(1)
java集合
1. 集合关系图
-
集合接口
terface.png)
-
实现类
2. LinkedList与ArrayList
2.1常用api,迷惑看https://docs.oracle.com/javase/7/docs/api/
-
构造
-
ArrayList() 构造一个初始容量为0的空列表,官方文档上说是10, 我认为不正确。源码中构造函数中数组指针指向一了空数组,尽管size字段在申明时初始化为10, 但是不代表构造完成后数组大小为10。当插入元素时才开始扩容为10。
int[] array = {}; // 等价与int[] array = new int[0] // array长度为0,但是不为null // null表示这个变量指向的对象为不存在,还没有给对象分配内存空间 // 此处的array指向了一个对象,只不过这个对象数组长度为零罢了。
- ArrayList(Collection<? extends E>) 构造一个包含集合的元素,按照他们由集合迭代器返回的顺序构建ArrayList。如果集合内的元素Class一样,也就是说类型一样,直接指向Collection。如果是子类,利用Arrays.copy()复制,进行类型强转。
- ArrayList(int initailCapacity) 构造具有初始容量的ArrayList,一般而言,如果事先知道有多少个元素,最好指定容量,避免不必要的resize()。尽管数组容量不为0, 但是有效元素个数size为0!!!
-
-
增
-
boolean add(E e) 增加元素到列表末尾
-
boolean add(int index, E element) 在索引index前面插入element。
List<Integer> array = ArrayList(10); array.add(2, 5); // 上面的代码出现数组越界异常 // 我以为声明了10个空间大小,每个初始化为0,所以我可以这么干啊。 // 尽管声明了大小为10的数组,但是size = 0, size为有效元素的个数。 // add()是针对下标在0-size-1之间的数组。
- boolean addAll(Collection<? extends E>) Collectin加到arraylist尾部
-
-
删
-
boolean remove(int index) 删除index下标,当然了,index也必须时在0-size-1之间
-
boolean remove(Object 0) 删除第一个元素0,内部使用equals()比较
// 贴一段我觉得写得很棒的代码 // 如果我实现下面的逻辑,肯定是return到处扔,肯定要把break换成fastRemove(es, i)和return true // 要是需求变了,要求remove失败返回true, 那就拉胯了。 public boolean remove(Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found;//跳出found } else { for (; i < size; i++) if (o.equals(es[i])) break found;//跳出found } return false; } fastRemove(es, i); return true; }
-
-
改
- E set(int index, E element) 返回原来的值
-
查
- E get(int index)
-
其他
- int size() 有效元素个数
- int indexOf(Object o) 返回元素下标, 内部使用equals比较大小
- Iterator
iterator() 返回迭代器 - Object clone()返回浅拷贝arrayList()
- contains(Object o) 内部使用equeals()
- Object[] toArray() 返回对应的数组
LinkedList, 除了ArrayList的一些操作,还可以当栈,队列,双端队列,所以api要多一点
-
构造函数
- LinkList()
- LinkList(Collection<? extend E> c)
-
增
-
boolean addFirst(E e) boolean addLast(E e) 双端队列常用操作
-
add(E e) 队尾部加
-
-
删
-
E remove() 删除第一个节点
-
E removeFirst()
-
E removeLast()
-
E poll() 删除第一个节点
-
E pollFirst()
-
E pollLast()
-
-
改
- set(in index)
-
查看
-
E peek() 获得第一个元素
-
E peekFirst() 获得第一个元素
-
E peekLast() 获得最后一个元素
-
E getFirst()
-
E getLast()
-
2.2 内部实现分
-
ArrayList : 可扩容的动态数组
- 线程不同步。
- 默认初始容量为 10,当数组大小不足时容量扩大为 1.5 倍。
- 为追求效率,ArrayList 没有实现同步(synchronized),如果需要多个线程并发访问,用户可以手动同步,也可使用 Vector 替代。
-
LinkedList: 双向链表
-
线程不同步。
-
双向链接实现。LinkedList 同时实现了 List 接口和 Deque 接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。
-
当你需要使用栈或者队列时,可以考虑使用 LinkedList,一方面是因为 Java 官方已经声明不建议使用 Stack 类,更遗憾的是,Java 里根本没有一个叫做 Queue 的类(它是个接口名字)。关于栈或队列,现在的首选是 ArrayDeque,它有着比 LinkedList(当作栈或队列使用时)有着更好的性能
-
Vector
:实现同步的可扩容动态数组-
线程同步。它的同步是通过
Iterator
方法加synchronized
实现的。 -
默认初始容量为 10,当数组大小不足时容量扩大为 2 倍。
-
2.3 区别与联系
- ArrayList底层是数组,可以通过下标直接定位到某个元素,时间复杂度为O(1),所以ArrayList更擅长read。当write的时候,如果是数组中间插入或者删除某个元素,那么则需要移动大量的元素。当我们只是read数据,或者是在末尾插入或者删除数据时,建议用ArrayList
- LinkedList底层是双向链表,当我们需要read某个元素时,可以从头或者从尾部开始遍历,具体取决于离头部近还是离尾部近。当需要wirte数据时,只用移动指针。所以,LinkedList更适合存储那些常常被修改的数据。