集合:就是用来存放数据的一个容器
Java提供集合类
它的长度(存储个数)可以改变
能存储任意对象
长度随存储的元素增加而增加
(增加方式:再创建一个新的数组容量增加50%,把原数据复制到新数组中,抛弃原数组,等待被回收处理)
与数组的区别
数组能存放基本数据类型与引用数据类型
集合只能存放引用数据类型(放入的基本数据类型,会自动装箱,把基本数据类型转成对象)
数组长度固定
集合的长度是可以改变的
Collection(接口)
List(接口)(有序,数据可重复)
ArrayList(数组)
LinkedList(链表)
Vector(数组)
Set(接口)(无序,数据不可重复)
HashSet(Hash算法)
LinkedHashSet(链表)(有序,但数据不可重复)
TreeSet(二叉树)
一些常用的方法
add() 向集合添加元素
remove() 从集合中移除指定的元素
clear() 从此集合中删除所有元素
isEmpty() 判断集合是否为空
size() 返回此集合中的元素个数,有几个元素
contains() 判断是否包含某一个元素
toArray() 把集合转成数组(数组中数据会向上转型,Object类型)
addAll() 合并集合
removeAll() 删除两个集合的交集
containsAll() 判断调用的集合是否包含传入的集合
retainAll() 取交集,把交集的集合赋给调用者(返回boolean:调用的集合改变,返回true,否则返回false(调用的集合就是交集时))
List
add()
add(int index, E element) 将指定元素插入此列表中的指定位置(注意:index <= size)
get(int index) 获取指定位置的元素
LinkedList
addFirst() 在开头(第一个位置)插入指定的元素
addLast() 在末尾插入指定的元素
removeFirst() 删除并返回第一个元素
removeLast() 删除并返回最后一个元素
get(int index) 返回指定位置的元素
HashSet
对于自定义的对象,添加到HashSet中时,想要去重(去除重复)
需要覆盖自定义的对象的hashCode()与equals()
LinkedHashSet
是使用链表实现的,是Set集合中,唯一可以保证元素顺序的,但数据不重复(去重)
TreeSet
会对添加的元素进行排序(同时保持唯一性,去重)
存放的元素类型必须一致
自定义的对象不能直接添加到TreeSet,需要实现Comparable接口,覆盖compareTo()方法
对于compareTo()方法的返回值:
返回值为0:TreeSet集合中只能添加第一个元素
返回值为正数:都能添加到集合中,显示时,顺序显示
返回值为负数:都能添加到集合中,显示时,逆序显示
比较器
默认情况下,比较时会调用对象的compareTo()进行比较,如果自己传入比较器,就不会调用compareTo(),会使用自己传入的比较器进行比较
使用比较器:
需要实现接口comparator,定义一个类来实现这个接口,覆盖里面的方法
ArrayList:查询数据较快,增删数据较慢
LinkedList:增删数据较快,查询数据较慢
ArrayList与Vector的区别:Vector上锁,更安全(但同时会降低效率)
将数组转成集合
int[] arr = {10,20,30};
List list = Arrays.asList(arr); -> List<int []> list = Arrays.asList(arr);
将数组转成集合,可以以面向对象的方式来操作数组,但是不能增添和删除元素,集合中其他的处理方式都是可以使用的
将基本数据类型数组,转成集合时,只是把数组当成一个对象
此时,没有意义(此时的list.size() 等于1,在集合中只存放了一个地址)
在开发中不会把基本数据类型的数组转成集合
Integer[] arr2 = {10,20,30}; // 会自动装箱
List list2 = Arrays.asList(arr2); -> List<Integer> list2 = Arrays.asList(arr2);
此时,list2.size() 等于3,集合中存放了三个对象(10、20和30)
将集合转数组
List<String> list = new ArrayList<>(); list.add("qwer"); list.add("asdf");
Object[] obj = list.toArray();
String[] strArr = list.toArray(new String[0]); // String[] strArr = list.toArray(new String[5]);
// (0 < 2) 静态开辟空间,若开辟的空间小于size,会自动创建一个和size一样大小的空间
// (5 < 2) 若开辟的空间大于size,会以自定义大小开辟空间,但未填充的空间单位为null
System.out.println(Arrays.toString(strArr)); // 结果:[qwer, asdf]
注意(并发修改异常):在迭代时进行增删、处理,须谨慎处理,使用可用的增删方法
modCount == expectedModCount
迭代器
Iterator 放置Iterator中的内容会自动类型提升,Object类型
next() 把当前的内容取出,并后移一位
hasNext() 判断迭代器中是否还有元素
remove() 删除当前正在迭代集合的元素(正在便利的元素)
ListIterator
List自己的迭代器
add() 迭代时可增添元素的方法
泛型
泛型:广泛通用的类型(起初类型未知,在使用时才确定其类型)
在使用时需指明其类型(必须是引用类型),否则默认Object类型
前后类型必须保持一致
后面的类型可以省略(菱形语法)
泛型其实是语法糖(本质还是Object类型,内部其实仍然做了强转)
通配符:<?> 表示未知
通配符只用来做接受使用
泛型的上限:限定元素的类型必须是指定类型,或指定类型的子类
泛型的下限:限定元素的类型必须是指定类型,或指定类型的父类
泛型的擦除:(把泛型给去掉)
将有泛型的集合(list1) 赋给 没有泛型的集合(list2),没有泛型的集合(list2)仍然没有泛型
List<String> list1 = new ArrayList<>();
List list2 = null;
list2 = list1; // 此时list2没有泛型