Collection 集合类
ArrayList:
基于动态数组的List
它有两个重要的变量,size为存储的数据的个数、elementData 数组则是arraylist 的基础,因为他的内部就是通过这个数组来存储数据的。
private int size;
private transient Object[] elementData;
优点:
1,随机访问 调用get()、set()的时间复杂度为O(1),很高效
public E get(int index) {
rangeCheck(index); return elementData(index); //内部通过数组索引获取数据,所以高效
} public E set(int index, E element) {
rangeCheck(index); E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
2,尾部添加 add(E e)E为泛型,影响因素为扩容,扩容大小为1.5倍,需要进行内部数组的复制
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
缺点:
1,删除数据的效率相对较低,时间复杂度O(n) 主要影响因素为数据移动和遍历数组
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;
}
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;
}
2,头部添加元素 时间复杂度O(n) ,影响因素数据移动
public void add(int index, E element) {
rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index); //索引及之后的数据都要向后移动一位
elementData[index] = element;
size++;
}
3, 查找元素 indexof() 时间复杂度O(n),影响因素遍历数组
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;
}
LinkedList:
基于双向链表
三个重要的变量,1、int size 2、Node<E> first 3、Node<E> last
size指LinkedList存储的元素的个数,first 指头结点,last 指尾结点
ArrayList 基于动态数组,需要分配特定的存储空间、内存地址连续。
LinkedList 基于双向链表,不需要分配特定存储空间、内存不连续,通过结点的头尾指针连接前后结点。
优点:
1,头部插入,删除效率高 时间复杂度O(1) 他不需要像ArrayList 那样要移动头部之后的所有元素
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f); //新建一个结点,前结点为null,元素 e,后结点为 f
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC,清空元素和尾指针
first = next; //此结点的后继结点置为头结点
if (next == null)
last = null;
else
next.prev = null; //
size--;
modCount++;
return element;
}
2,尾部插入、删除 效率很高 时间复杂度O(1),相对于ArrayList来说不用扩容
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
缺点:
1,随机访问 LinkedList的随机访问访问方面比较慢,时间复杂度O(n/2) 而ArrayList的随机访问为O(1)
Node<E> node(int index) {
// assert isElementIndex(index);
// 访问时,先获取该位置的结点,然后返回结点的值
if (index < (size >> 1)) { // 如果位置小于LinkedList元素个数的一半,则从头开始遍历,否则从后开始遍历,这也是时间复杂度为n/2的原因
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
2,查找元素 和ArrayList 一样需要遍历整个list,时间复杂度为O(n)
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
3,中间部分插入和删除 时间复杂度为O(n),影响原因需要先定位到指定元素。定位后修改的效率很高
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
LinkedList在执行中间插入和删除时比ArrayList高效,随机访问反面比较逊色。
向前遍历List,不修改List对象本身,可以用foreach
Iterator 只能向前移动,可以用next(),和remove()联合起来删除List中的对象
public static void main(String[] args) {
List<Integer> iList=new ArrayList<>();
for (int i = 0; i < 8; i++) {
iList.add(i);
} for (Integer i : iList) {
System.out.println(i);
} //foreach 遍历list Iterator<Integer> iterator=iList.iterator();
while (iterator.hasNext()) {
iterator.next();
iterator.remove(); //迭代器遍历list,并进行删除
}
System.out.println(iList); }
listIterator只能用于list类的访问,可以双向移动
TreeSet将元素储存在红-黑树,数据结构中。HashSet使用散列函数。LinkedHashSet使用散列和链表维护插入顺序。
Collection 集合类的更多相关文章
- Java API ——Collection集合类 & Iterator接口
对象数组举例: 学生类: package itcast01; /** * Created by gao on 15-12-9. */ public class Student { private St ...
- Java:Collection集合类
特点:只能用于存储对象,集合长度时可变的,集合可以存储不同类型的对象. 数组和集合类同时容器,不同的是: 1.数组虽然也可以存储对象,但是长度是固定的:集合长度时可变的. 2.数组中可以存储基本数据类 ...
- java中的Collection集合类
随着1998年JDK 1.2的发布,同时新增了常用的Collections集合类,包含了Collection和Map接口.而Dictionary类是在1996年JDK 1.0发布时就已经有了.它们都可 ...
- Java Collection 集合类大小调整带来的性能消耗
Java Collection类的某些详细实现因为底层数据存储基于数组,随着元素数量的添加,调整大小的代价非常大.随着Collection元素增长到某个上限,调整其大小可能出现性能问题. 当Colle ...
- Java collection 集合类架构
https://www.cnblogs.com/fireflyupup/p/4875130.html Collection List 在Collection的基础上引入了有序的概念,位置精确:允许相同 ...
- java9第5篇-Collection集合类的增强与优化
我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...
- Java集合类: Set、List、Map、Queue使用场景梳理
本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E ...
- Java集合类: Set、List、Map、Queue使用
目录 1. Java集合类基本概念 2. Java集合类架构层次关系 3. Java集合类的应用场景代码 1. Java集合类基本概念 在编程中,常常需要集中存放多个数据.从传统意义上讲,数组是我们的 ...
- 基础知识《六》---Java集合类: Set、List、Map、Queue使用场景梳理
本文转载自LittleHann 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F% ...
随机推荐
- jquery mobile cannot be created in a document with origin 'null' and URL
jquery mobile cannot be created in a document with origin 'null' and URL http://zhidao.baidu.com/lin ...
- HDU 5687 字典树插入查找删除
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5687 2016百度之星资格赛C题,直接套用字典树,顺便巩固了一下自己对字典树的理解 #include< ...
- php的字符串转2进制函数
<?php $file1 = '16.jpg'; $file2 = 'test.txt'; $file3 = '47.jpg'; $size = filesize($file1); echo ' ...
- android service被系统回收的解决方法
自己的app的service总是容易被系统回收,搜罗了一下,基本上的解决思路有以下几种: 1.把service写成系统服务,将永远不会被回收(未实践): 在Manifest.xml文件中设置persi ...
- 破解TexturePacker加密资源
http://blog.csdn.net/ynnmnm/article/details/38392795 最近我们要开一个新项目,UI与交互打算借鉴当前正火的<圣火英雄传>,程序开发为了和 ...
- __get().__set.__isset,__unset魔术方法
一般来说,总是把类的属性定义为 private .这更符合现实的逻辑. 但是对属性的读取和赋值操作非常频繁的,因此在PHP中,预定义了两魔术方法 "__get()"用来获取私有成员属性值的,只有一个参 ...
- (原)android中的动画(三)之动画监听&页面切换动画
1.动画也可以设置监听事件,例如在动画结束时需要执行某操作 把要执行的代码写在onAnimationEnd()回调方法中即可: anim.setAnimationListener(new Animat ...
- php源码安全加密之PHP混淆算法.
php源码安全加密的前世今生,本想发在教程区中.不知道怎么发,就写在这里面吧.PHP加密,解密是一直的话题,本人菜鸟,今天就简单向大家介绍一下并说说其中原理.提供一些加密的混淆算法.一\PHP的加密总 ...
- 1.AngularJS初探
1.需要什么前端开发环境 1)代码编辑工具 webstorm 2)断点调试工具 chrome插件Batarang 3)版本管理 tortoiseGit 4)代码合并和混淆工具 grunt-contri ...
- 浅谈python的import
动态加载模块: 使用__import__ c=__import__('sys') 等价于 import sys 不过前者可以在执行时决定. 静态加载: 也就是常规的import from xxx im ...