集合的由来:数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少
数组和集合的区别
-
数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
-
集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
-
数组长度是固定的,不能自动增长
-
集合的长度的是可变的,可以根据元素的增加而增长
集合分两大类
Collection:单列集合
Map:双列集合
集合相比与数组可以存储多个数据类型数据,而且可以随时增减长度。
集合是通过调用size()方法来获取长度
迭代器
集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可
在迭代过程中不能操作集合中的元素,否则会抛出ConcurrentModificationException异常
ArrayList和LinkedList的区别,在于ArrayList查找快,LinkedList增删快。ArrayList的底层结构是数组,所以当需要查找某个元素的时候,只需要根据索引查找即可。但增删慢,比如说:在布置考场的时候,需要给每个桌子贴考号,但是当贴到后面的时候发现前面少贴了一个,这时需要把后面的考号重新撕下来,重新贴一遍。LinkedList增删快时因为他是链表结构,不需要顾及其他元素的位置,比如说:军训站队的时候,你不需要记住所有人的位置,你只需要知道你前后面人的位置,就知道你站在哪。LinkedList查找慢,是因为它只给了链表头和尾,当你需要找中间位置的元素,它是从前或后往中间找,所以查找慢
比较ArraysList和LinkedList的增删速度
ArrayList<String> array = new ArrayList();
LinkedList<String> link = new LinkedList();
//ArrayList增加元素所需时间
long start1 = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
array.add("wuhan"+i);
}
long end1 = System.currentTimeMillis();
//LinkedList增加元素所需时间
long start2 = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
link.add("wuhan"+i);
}
long end2 = System.currentTimeMillis();
System.out.println("ArrayList增加元素所需时间:"+(end1-start1));//54
System.out.println("LinkedList增加元素所需时间:"+(end2-start2));//32
比较ArraysList和LinkedList的查找速度
ArrayList<String> array = new ArrayList();
LinkedList<String> link = new LinkedList();
for (int i = 0; i < 1000000; i++) {
array.add("wuhan"+i);
}
for (int i = 0; i < 1000000; i++) {
link.add("wuhan"+i);
}
//ArrayList查找元素所需时间
long start1 = System.currentTimeMillis();
array.get(500000);
long end1 = System.currentTimeMillis();
//LinkedList查找元素所需时间
long start2 = System.currentTimeMillis();
link.get(500000);
long end2 = System.currentTimeMillis();
System.out.println("ArrayList查找元素所需时间:"+(end1-start1));//0
System.out.println("LinkedList查找元素所需时间:"+(end2-start2));//6
ArraysList
-
查找快,修改也快
-
初始容量为10
-
底层结构是数组
-
线程不安全,效率高
add(Object obj)
添加元素,可以是任意类型数据
ArrayList list = new ArrayList();
list.add(1);
list.add("a");
list.add(true);
System.out.println(list);//结果为[1, a, true]
contains(Object obj)
比较集合里面是否包含obj
ArrayList list = new ArrayList();
list.add(1);
list.add("a");
list.add(true);
boolean contains = list.contains(1);
boolean contains1 = list.contains("b");
System.out.println(contains);//结果为true
System.out.println(contains1);//结果为false
get(int index)
根据下标获取集合中的数据,返回类型是Object,因为ArrayList的底层结构是Objec类型数组,如果需要用其他类型数据来接收数据,需要强转,注意的是强制的类型必须是集合中元素的类型,比如说不可能把字符串a转换成整型1,否则会发生ClassCastException异常,解决此办法需要用到泛型。
泛型:规定集合中的数据的类型,把运行是异常提前到编译时期。
规定以后声明集合是需要带泛型。
ArrayList list = new ArrayList();
list.add(1);
list.add("a");
list.add(true);
Object object = list.get(1);
System.out.println(object);//结果为a
remove(int index),remove(Object o)
可以通过下标删除指定元素,也可以直接删除指定的元素,注意,如果元素类型都是int类型,如果你又想删除指定的元素,比如说元素是1,2,3。想删除数字1,但输入数字1的时候却删除的是数字2,是因为在源代码里面,remove(int index)方法是remove的重写方法的第一个,所以优先执行。
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.remove(1);
System.out.println(list);//结果为[a, c]
removeAll(Collection c)
删除所有元素
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
ArrayList list1 = new ArrayList();
list1.add("b");
list1.add("c");
list1.add("d");
list.removeAll(list1);
System.out.println(list);//结果为[a, e]
retainAll(Collection c)
仅保留包含c里面的集合的元素
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("d");
ArrayList list1 = new ArrayList();
list1.add("a");
list1.add("b");
list1.add("c");
list.retainAll(list1);
System.out.println(list);//结果为[a, b, c]
toArray()
把集合转换成数组,数组类型是Object
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
Object[] array = list.toArray();
System.out.println(Arrays.toString(array));//结果为[a, b, c]
把数组转换成集合,使用Arrays的asList,数组转换成集合是不能更改长度的,增删都不行。
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
Object[] array = list.toArray();
List<Object> asList = Arrays.asList(array);
System.out.println(asList);//结果为[a, b, c]
循环遍历集合。for循环---foreach循环---迭代器遍历
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
//for循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//foreach循环
for (Object obj : list) {
System.out.println(obj);
}
//迭代器遍历,迭代过程中不能增删元素,否则会报ConcurrentModificationException异常
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object object = (Object) iterator.next();
list.remove(object);
System.out.println(object);
}
比较使用for循环和迭代器两者的快慢
ArrayList<String> list = new ArrayList();
for (int i = 0; i < 1000000; i++) {
list.add("wuhan"+i);
}
//for循环打印所需要的时间
long start1 = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
long end1 = System.currentTimeMillis();
//迭代器打印所需要的时间
Iterator iterator = list.iterator();
long start2 = System.currentTimeMillis();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
long end2 = System.currentTimeMillis();
System.out.println("for循环打印所需要的时间:"+(end1-start1));//for循环打印所需要的时间:5923
System.out.println("迭代器打印所需要的时间:"+(end2-start2));//迭代器打印所需要的时间:5100
LinkedList
-
查询慢,修改也慢
-
增删快
-
初始容量为0
-
底层结构是链表
-
线程不安全,效率高
addFirst(Object obj)
在集合头部添加元素,返回类型是Object
addLast(Object obj)
在集合结尾添加元素,返回类型是Object
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.addFirst("d");
list.addLast("e");
System.out.println(list);//结果为[d, a, b, c, e]
offerFirst(E e)
在集合头部添加元素,返回类型是boolean
offer(E e)
在集合结尾添加元素,返回类型是boolean
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
boolean offerFirst = list.offerFirst("d");
boolean offer = list.offer("e");
System.out.println(list);//结果为[d, a, b, c, e]
element()
检索但不删除第一个元素
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
Object element = list.element();
System.out.println(element);//结果为a
poll()
检索并删除,一般指第一个元素
pollFirst()
检索并删除第一个元素
pollLast()
检索并删除最后一个元素
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Object poll = list.poll();
Object pollFirst = list.pollFirst();
Object pollLast = list.pollLast();
System.out.println(list);//结果为[c, d]
pop()
弹出第一个元素
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Object pop = list.pop();
System.out.println(pop);//结果为a
System.out.println(list);//结果为[b, c, d, e]
push(Object obj)
推送到此集合中,一般推送到第一个
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.push("f");
list.push("g");
System.out.println(list);//结果为[g, f, a, b, c, d, e]
在LinkedList中有一个特有的迭代器,继承自Itartor的子接口ListIterator
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
ListIterator listIterator = list.listIterator(3);//根据索引迭代
while(listIterator.hasNext()) {//往后迭代
System.out.print(listIterator.next()+" ");//结果为d e f,包含索引
}
LinkedList list = new LinkedList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
ListIterator listIterator = list.listIterator(3);//根据索引迭代
while(listIterator.hasPrevious()) {//往后迭代
System.out.print(listIterator.previous()+" ");//结果为c b a,不包含索引
}
Vector
-
线程安全,效率低
-
初始容量为10
-
底层结构是数组
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
Vector和ArrayList的区别
-
Vector是线程安全的,效率低
-
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList的区别
-
ArrayList底层是数组结果,查询和修改快
-
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
-
查询多用ArrayList
-
增删多用LinkedList
-
如果都多ArrayList