一、java.util.List
List继承自Collection,是集合中非常常用的一个子类型。
特点是:可以放重复元素,并且有序,其提供了一套通过下标操作元素的方法。
二、常见的实现类:
java.util.ArrayList:内部使用数组实现,查询性能更好。
java.util.linkedList:内部使用链表实现,增删元素性能更好,首位增删元素性能最佳。
三、List的方法:
1、[E] gex(index)
获取指定下标对应的元素,下标从0开始,到size()-1
如果下标超出合法范围,会抛出下标越界异常:IndexOutOfBoundsException
2、[E] sex(index,E e)
将给定元素设置到指定位置,返回值为该位置原有元素。
【练习】
在不创建新的集合的前提下,将元素翻转,利用get和set实现。
for (int i = 0; i对于上题:java.util.Collections是集合的工具类,里面提供了很多操作集合的方法。
3、[E数组] reverse(List list):
用于反转集合元素,返回翻转数组
4、[void] add(int index,E e):
将给定元素添加到指定位置,原位置及后续元素顺序向后移动,相当于插入操作。
5、[E] remove(int index):
删除并返回指定位置的元素。
当我们通过一个List集合获取到一个子集后,对这个子集的任何操作就是对原集合这段元素的操作。
6、[List] subList(int start,int end)
获取当前集合中指定范围内的子集
7、[void] clear():
清空数组
8、asList() :
数组的工具类Arrays提供了一个静态方法:asList(),可以将一个数组转换为一个List集合。
!!!通过数组转换而来的集合,对该集合的元素操作就是对原数组操作!!!
由于数组是定长的,因此从数转换来的集合是不可以调用增删元素等会影响数组长度的方法的,否则会抛出异常:UnsupportedOperationException
如果想要向集合中增删元素,需要自行创建一个集合,然后将原集合元素导入到该集合中即可。
所有的集合都支持一个参数类型为Collection的构造方法,作用是在创建当前集合的同时包含给定集合的所有元素。
四、List使用sort进行排序:
① sort一个参数:Collections.sort(List list)
该方法对List集合进行自然排序,即从小到大排序
但是该方法对集合有一个要求:元素必须实现了接口Comparable,否则编译不通过。
该接口中有一个抽象方法,要求实现类重写,用于定义该类元素之间的大小关系。java中很多类都实现了它,比如String、包装类。
当我们调用一个方法,而这个方法反过来还要我们为其修改其他地方的代码(比如这里要求我们修改Point2类取实现Comparable接口并重写方法)这种现象称为侵入性,侵入性越高,需要更改的代码就越多,对我们越不利。写程序应该避免侵入性。
Listlist = new ArrayList<>(); Random ran = new Random(); for (int i = 0; i < 5; i++) { list.add(ran.nextInt(90)+10); } System.out.println(list); //对集合元素进行排序,从小到大 Collections.sort(list); System.out.println(list); ②sort两个参数:Collections.sort(List list,比较器)
Collections提供了一个重载的sort方法,需要再传入一个参数:比较器。
Comparator是比较器接口,实现它就要重写方法:
compare()来定义两个要比较的元素的大小规则,通常我们直接以匿名内部类的形式创建,为集合的排序使用。该方法中的两个参数就是要比比较的两个元素,方法返回值为比较大小的关系,定义如下:
当返回值>0,表示参数o1比o2大
当返回值<0,表示参数o1比o2小
当返回值=0,表示参数o1与o2相等
即:从小到大为o1-o2,从大到小为o2-o1
//对集合元素进行排序,从大到小 Collections.sort(list,(((o1, o2) -> o2-o1))); System.out.println(list);有时候集合已经实现了Comparable接口,可以比较大小,但是其比较规则不满足我们的排序需求时,我们仍然可以使用重载的sort方法,临时传入一个比较规则进行排序。
String实现了Comparable接口,可以直接使用sort进行比较,默认按照字符对应int类型大小排序。
五、List扩容
ArrayList底层维护了一个Object[] elementData用来存储数据
JDK6是:当创建一个ArrayList对象时,直接创建一个容量为10的数组。
JDK8是:当创建一个ArrayList对象时,创建一个空数组 private static final Object[],优化内存,相当于是延迟分配对象数组空间,当第一次插入元素时才分配10个对象空间。当超过10个元素时,底层会自动扩容,扩容至旧容量的1.5倍。
DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {} //创建空 private static final int DEFAULT_CAPACITY = 10;//分派10 int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容*1.5六、linkedList 1、ArrayList、linkedList和Vector的区别:假设需要添加20个数据,则:在第一次添加的时候将ArrayList容量变为10,之后扩容会按照1.5倍增长。 也就是在添加第11个数据的时候,ArrayList继续扩容变为10*1.5=15; 当添加第16个数据的时候,ArrayList继续扩容为15*1.5=22个。(>>向下取整)
都实现了List接口
ArrayList和Vector底层是数组,查找快;linkedList底层是链表,增删快。
ArrayList是线程不安全的;Vector是线程安全的,ArrayList的执行效率略高于Vector。
2、特有的方法:1、 [void] addFirst(E e):向链表头插入一个元素
2、 [void] addLast(E e):向链表尾插入一个元素
3、 [ E ] getFirst(E e):获取链表的第一个元素
4、 [ E ] getLast(E e):获取链表的最后一个元素
3、linkedList和get方法实现机制:比较传入的索引值index与集合长度size/2,如果是index小,那么从第一个元素开始顺序循环, 直到找到位置;如果是index大,那么从最后一个元素开始倒序循环,直到找到位置。
也就是说越靠近中间位置的元素,调用get方法遍历的次数就越多,效率也就越低,而且随着新集合越来越大, get方法的执行效率反而会下降,因此使用的时候,不建议使用这种方式读取数据。
可以使用getFirst和getLast直接获取集合中的第一个和最后一个元素。



