集合类
- ArrayList类
* 与数组比较相似,不同的是集合的长度可以改变,数组的长度一旦固定便不可改变;
* 集合是用来存储一组元素的;
默认扩容1.5倍
* 由于ArrayList底层是一个Object [ ] ,所以什么类型都能存进去;
private static final Object[] EMPTY_ELEMENTDATA = {};
* 常用的方法:
(1) add(E e):
在集合的后面添加一个元素;
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
//如果添加成功,则返回true
return true;
}
add(int index,E e);
在index位置添加一个元素;
public void add(int index, E element) {
//检查index是否合法
rangeCheckForAdd(index);
//确定需要的数组长度是size+1,是否够用
ensureCapacityInternal(size + 1);
//将数组从index开始复制size-index个到数组的index+1位置
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//将数组index的位置填充
elementData[index] = element;
//数组的长度加1
size++;
}
addAll(Colletion c):
在集合的后面添加一个集合;
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
//确定当前数组的容量是否够用
ensureCapacityInternal(size + numNew);
//将需要添加的集合的数组从0开始添加到结束,添加至 集合对象的数组里面
System.arraycopy(a, 0, elementData, size, numNew);
//集合数组的长度=原长度+新的集合数组长度
size += numNew;
//如果新集合元素长度为0,则添加失败
return numNew != 0;
}
add(int index,Collection c):
在指定位置添加一个集合;
public boolean addAll(int index, Collection<? extends E> c) {
//确定index是否合法
rangeCheckForAdd(index);
//将集合转化成数组
Object[] a = c.toArray();
//numNew是此数组的长度,也就是新添加的集合的长度
int numNew = a.length;
//确定容量是否够用
ensureCapacityInternal(size + numNew);
//numMoved是元集合需要将元集合中的几个元素移动
int numMoved = size - index;
if (numMoved > 0)
//将元集合的从index开始的元素,往后移动numNew个位置,中间空出来
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//将新的数组填充至刚才空出来的位置
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
(2) clear():
将集合里面的元素全部清除干净;
public void clear() {
//调用本类中的函数
removeRange(0, size());
}
protected void removeRange(int fromIndex, int toIndex) {
//将集合用迭代器遍历
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
//依次删除
it.next();
it.remove();
}
}
(3) contains(Object obj):
在集合里面找寻指定元素;
返回值类型是boolean型;
public boolean contains(Object o) {
return indexOf(o) >= 0;//调用本类的indexOf方法
}
public int indexOf(Object o) {
//如果o是nul,则遍历集合中有没有null
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
//返回null所在索引的值
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
(4) ensureCapacity(int minCapacity):
确保集合的容量是否够用;
返回值类型是boolean型;
(5) get(int index):
返回索引位置处的元素;
public E get(int index) {
rangeCheck(index);
//这个比较好理解
return elementData(index);
}
(6) indexOf(Object obj):
查找指定元素在集合里面第一次出现的位置;
返回值是它的索引;
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
lastIndexOf(Object obj):
查找指定元素在集合里面最后一次出现的位置;返回值是它最后一次出现的索引;
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
(7)isEmpty();
判断这个集合是否是一个空集合;
返回值类型是boolean型;
public boolean isEmpty() {
return size == 0;
}
(8) remove(int index);
将index位置的元素删除;
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
//将index位置处的元素用剩余的元素覆盖掉,此时多出了一个最后index处的元素
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将最后index处的元素置位null
elementData[--size] = null;
return oldValue;
}
remove(Object obj);
删除元素obj;
//这个和上一个相似,在这里就不具体解释了
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
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
}
removeAll(Object obj);
求两个集合的差集;
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
//这个for循环为了找出 两个集合中的不同元素,此时传进来的complement==false
for (; r < size; r++)
//等价于 !c.contains(elementData[r])
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
//找出集合对象中 除了相同元素之外剩下的元素,添加在elementData数组中
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
//找出参数C集合的除了相同元素之外的元素,添加在elementData数组中
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
retainAll()Object obj);
求两个元素的交集;
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
//找出两个集合中的相同元素 此时传进来的complement==true
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
//每次都是r == size
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
//将elementData剩余
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
(9)set(int index,E e);
将index位置处的元素设置成e;
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
(10)size();
求集合的有效元素个数;
public int size() {
return size;
}
(11)subList(int begin,int end);
将集合从begin开始截取到end;
(12)toArray();
将集合转化成数组;
返回值类型是数组类型;
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
toArray(T [])
将集合转化成数组;
返回值类型是数组类型;
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
(13)trimToSize();
变成有效元素那么长;
(14)Iterator();
迭代器;
2. Vector类
是ArrayList的早期版本,效率低,安全性高;
默认扩容2倍;
3. Stack类
构造方法只有无参构造;
继承Vector类;
常用方法:
push(E e)
将某一个元素压入栈顶;相当于add()
E = pop()将某一个元素从栈顶取出并删除;相当于remove()
E = peek()查看栈顶的一个元素 不删除;相当于get()
boolean = empty()判断栈内元素是否为空;相当于isEmpty()
int = search(E e)查找给定元素在栈中的位置;相当于indexOf()
4. Queue接口
通常子类LinkedList ArrayDeque
通常用无参构造方法创建对象;
一般方法
add()
element(E e)------>get()
remove()
boolean = offer(E e)---->add()
E = peek()----->element()
E = poll()------>remove()
5. LinkedList类
继承List 实现 Queue
双向链表 适合插入删除 不适合遍历
最后一个进去的,第一个出来,LIFO(last in first out)
构建对象:无参 有参
常用方法:addFirst() addLast() removeFirst() removeLast()
- Set接口
实现类:HashSet类 TreeSet类
使用:
无序无重复 :我们使用的集合存放元素的顺序 集合内取出来的顺序不一致
集合本身具有自己的算法排布顺序 hash算法
元素可以是null元素,但是有且只能有一个null元素;
HashSet---->(HashMap(数组+链表)散列表 临接链表)
1. java.util
2.创建对象:有参、无参;
HashSet<String > hs = new HashSet();
3. 方法:
boolean = add(value);
addAll(collection c)
retainAll()
removeAll()
boolean = remove(Object o)
遍历:可以使用增强for循环来遍历
Iterator = hs. iterator()
Iterator是一个接口,里面有方法hasNext():判断里面是否有元素;next():判取出里面的元素;
size():返回里面有效元素的个数(没有重复的);
4. 无重复的原则
首先通过String和Person类型存储;
利用equals()方法比较;
如果想要Person对象的name一致,就要重写equals()方法;
但是重写了equals()方法之后,还没有产生重复的效果;
还另外一个方法起着作用,hashCode() 返回值是int型
set集合发现重复的元素,拒绝存入,存 的是第一个元素;
如果要把一个对象放入HashSet中,要重写该对象对应类的equals方法,同时要重写hashCode方法;
TreeSet------>TreeMap(二叉树,利用node(left,item,right))
java.util
无参 有参构造
无重复:需要实现Comparable接口,并且重写compareTo方法;
有序不重复的排列
利用iterator遍历 - HashMap
底层是数组+链表(Node Entry)的形式,默认数组有16个容量,每当达到容量的75%时,就会自动扩容;、
数组内存储的是hashcode码,如果元素的hashCode码相同,那么这两个元素就构成了链表;
不同的对象可能产生相同的hashcode码,但是不同的hashcode码一定对应不同的对象;
java.util 无参和有参构造创建对象;
HashMap<Integer,String> hm = new HashMap();
常用方法:
增:put( key,value) hm.put(1,“hyf”);
删:remove(key[,value]) hm.remove(1);
改:replace(key,value) replace(key,oldValue,newValue) hm.replace(1,“hyf1”);
查:Set = keySet() 获取所有元素的key值
API方法:
int = size() 元素有效个数;
boolean = containskey(key) ;是否有这个key值;
boolean = containsValue(value),是否含有value;
getOrDefault(key,DefaultValue) ,如果有元素key,那么返回key对应的value,如果没有,那么返回给定的DefaultValue;
boolean = isEmpty(),集合是否为空;
putAll(Map),将Map集合添加到已知对象的集合内;
putIfAbsent(key,value),返回key对应的value,如果没有此key值,那么就将这个key和value添加到集合内;
Set<Map.Entry<Integer,String>> = entrySet(),获取全部entry(Node)对象
map集合在什么情形下使用?
1.想要存储一组元素
数组 集合 如果存储的元素个数以后不变,那么用数组,如果发生改变,就用集合;
2.如果发现长度以后不确定------>集合
List Map Set
List家族是有序的
ArrayList 更适合遍历轮询
LinkedList 适合插入和删除
Stack 先进后出
Set家族无重复
Hash 性能更高
Tree 希望存进去的元素自动去重复,同时还能排序
Map (key - value) 通过唯一的key可以快速找到value
Hash 性能更高
Tree 希望存进去的元素key可以自动排序;