集合源码
源码分析
如何看源码:
脉络 解决什么问题,忽略掉不重要的一些细节
构造 add remove
理解代码运行过程
ArrayList
集合1
1、集合框架--Collection
2、ArrayList 和LinkedList
ArrayList:基于数组实现,查询效率高
LinkedList:基于链表实现,增删效率高
size():长度
add():添加
remove():删除
clear():清空
set():修改
3、泛型
限制类型
不用转型
泛型:<>
4、Collections
shuffle:
Collections.reverse(list);反转集合
Collections.checkedList(dogs,Dog.class):对加入数据的类型进行检查
5、HashSet
hashCode:确定桶的
equals:比较是否同一个对象,决定了这个元素是丢是留
LinkedHashSet是在HashSet的基础上新维护了一个双向链表
6、TreeSet
树:二叉树
两种排序:
用匿名内部类在构造TreeSet的时候放一个Comparator
用需要排序的类去实现Comparable
7、迭代器
iterator
Collection extends Iterable;
意味着只要是Collection的儿子都有迭代器
//获取迭代器
Iterator<T> itor = 集合.iterator();
//while
while(itor.hasNext()){
T t = itor.next();
}
注意:迭代器可以在迭代的同事删除当前元素
反向迭代器
8、Map
8.1 HashMap<K,V>
put(k,v);
remove(key)
get(key)
keySet():key的集合----Set
values():Collection
entrySet():Set<Entry<K,V>>
containsKey():是否包含这个键
8.2 Hashtable
线程安全的,效率低,使用少,键值不能为null
Properties类:
编写配置文件
8.3 LinkedHashMap
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
map.put("CN", "CHINA");
map.put("US", "AMERICA");
map.put("RU", "RUSSIA");
map.put("JP", "JAPAN");
map.put("FR", "FRANCE");
map.put("UK", "UNITEDKINGDON");
System.out.println(map);
}
8.4 TreeMap
public static void main(String[] args) {
TreeMap<Student, String> map = new TreeMap<Student, String>(new Comparator<Student>() {
public int compare(Student o1, Student o2) {
return o1.salary-o2.salary;
}
});
map.put(new Student("中国",50,10), "CHINA");
map.put(new Student("美国",20,21), "AMERICA");
map.put(new Student("俄国",30,23), "RUSSIA");
map.put(new Student("日本",40,34), "JAPAN");
map.put(new Student("法国",60,34), "FRANCE");
map.put(new Student("英国",100,66), "UNITEDKINGDON");
System.out.println(map);
}
9、源码分析
如何看源码:
脉络---解决什么问题,忽略掉不重要的一些细节
构造---》add--->remove
9.1 ArrayList
ArrayList<String> list =new ArrayList<String>(20);//1
ArrayList<String> list =new ArrayList<String>();//3
ArrayList<String> list =new ArrayList<String>(0);//1,2,3,4,6,9,13,19,28//9
list.add("111");
这两种方式定义集合,当集合长度达到20时,分别经历了多少次扩容?
public ArrayList() {
//构造一个无参的对象,就把一个空数组赋给elementData,这个数组实际上就是
//ArrayList的底层数据存储的地方
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//{};
}
//私有静态常量对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//对象数组的属性
transient Object[] elementData;
//添加方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); //private int size;---默认为0
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {//1
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//{}-DEFAULTCAPACITY_EMPTY_ELEMENTDATA,1 ---10
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//无参构造第一次满足
return Math.max(DEFAULT_CAPACITY, minCapacity);
// private static final int DEFAULT_CAPACITY = 10;
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {//10
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);//扩容-10
}
private void grow(int minCapacity) {//10--1
// overflow-conscious code
int oldCapacity = elementData.length;//0
int newCapacity = oldCapacity + (oldCapacity >> 1);//0
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;//10
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//扩容
}
以上是无参构造的执行过程
public ArrayList(int initialCapacity) {//20
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//modCount--模数 魔数 魔术
这个变量记录的是集合操作的次数---增删
//remove
public E remove(int index) {//下标
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
//get
1、ArrayList在无参构造的时候,设置对象数组为空
2、如果是无参构造出来的空集合,一开始长度为0,第一次执行添加操作的时候,会扩容到10
3、以后ArrayList满了的时候就会按照1.5倍进行扩容
4、如果构造的是带参的,那么直接扩容到参数指定的个数,特例如果参数为0,就从0开始扩容
源码解决ArrayList不可修改的问题
Arrays类里有一个ArrayList的内部类,这个类没有实现add,remove方法发,而是直接抛异常
String[] strs = {"aaa","bbb","ddd"};
List
这样得到的list集合只能读写,不能增删
9.2 LinkedList
无参构造:
public LinkedList() {
}
public boolean add(E e) {
linkLast(e);//后面添加元素
return true;
}
//链表的节点
private static class Node<E> {
E item;//数据---“aaa”
Node<E> next;//后继
Node<E> prev;//前驱
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
//添加元素
void linkLast(E e) {
final Node<E> l = last;//先把最后一个节点缓存起来
//这个节点是要添加的节点,前驱是上次最后的节点,后继为空
final Node<E> newNode = new Node<>(l, e, null);
//成员变量last保存当前要添加的节点为最后节点
last = newNode;
if (l == null)
//第一个节点,first=last=newNode
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
//删除指定元素
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {

浙公网安备 33010602011771号