1、List接口
-
特点:
有序的:集合中每一个元素都有它的索引,类似于数组下标,第一个元素的索引值是0。
不唯一:集合中允许有一样的元素。实现List接口的实现类有LinkedList,ArrayList,Vector和Stack。 -
常用方法:
添加元素: add(Object类型值)方法
获取元素:get(下标)方法
获取集合大小(存放元素个数: size()方法, 如果size()返回值为0,代表集合为空
判断集合是否包含某个元素: contains(元素)方法
判断集合是否非空:isEmpty()方法
集合一步转换为数组对象:调用toArray()方法
数组一步转换为集合:使用Arrays.asList(数组);
2、List接口常用实现类
1、ArrayList类
ArrayList实现了可变大小的数组
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加。
底层实现是数组容量自动扩充的,如果是空参构造,长度为0,调用add之后,初始10个长度,后续到达默认容量后,都自动扩容原有长度的一半,如果指定初始容量,不会自动扩容,实际上可变就是把之前数组内容拷贝到新的扩容的数组中
1、ArrayList没有同步策略,线程不安全。
2、ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高.
3、ArrayList允许存放null值元素
2、LinkedList类
1、LinkedList实现了List接口,
允许null元素。
2、LinkedList采用链表存储方式。
3、由于它的底层是用双向链表实现的,所以没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好
4、插入、删除元素时效率比较高,遍历和随机访问效率比较低,需要二分进行查找。
3、代码案例(部分在Collection介绍过)
get()与set()
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// List<String> list = new LinkedList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
/*
E get(int index)
获取指定下标对应的元素
*/
//获取第三个元素
String e = list.get(2);
System.out.println(e);
for(int i=0;i<list.size();i++){
e = list.get(i);
System.out.println(e);
}
/*
E set(int index,E e)
将给定元素设置到指定位置,返回值为该位置原有的元素。
替换元素操作
*/
//[one,six,three,four,five]
String old = list.set(1,"six");
System.out.println(list);
System.out.println("被替换的元素是:"+old);
}
}
重载的add()和remove()
import java.util.ArrayList;
import java.util.List;
/**
* List集合提供了一对重载的add,remove方法
*/
public class ListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
/*
void add(int index,E e)
将给定元素插入到指定位置
*/
//[one,two,six,three,four,five]
list.add(2,"six");
System.out.println(list);
/*
E remove(int index)
删除并返回指定位置上的元素
*/
//[one,six,three,four,five]
String e = list.remove(1);
System.out.println(list);
System.out.println("被删除的元素:"+e);
}
}
subList()方法
import java.util.ArrayList;
import java.util.List;
/**
* List subList(int start,int end)
* 获取当前集合中指定范围内的子集。两个参数为开始与结束的下标(含头不含尾)
*/
public class ListDemo3 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
System.out.println(list);
//获取3-7这部分
List<Integer> subList = list.subList(3,8);
System.out.println(subList);
//将子集每个元素扩大10倍
for(int i=0;i<subList.size();i++){
subList.set(i,subList.get(i) * 10);
}
//[30,40,50,60,70
System.out.println(subList);
/*
对子集元素的操作就是对原集合对应元素的操作
*/
System.out.println(list);
//删除list集合中的2-8
list.subList(2,9).clear();
System.out.println(list);
}
}
4、集合的排序
java.util.Collections类
- Collections是集合的工具类,里面定义了许多静态方法用于操作集合.
Collections.sort(List list)方法
- 可以对List集合进行自然排序(从小到大)
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* 集合的排序
* 集合的工具类:java.util.Collections提供了一个静态方法sort,可以对List集合
* 进行自然排序
*/
public class SortListDemo1 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for(int i=0;i<10;i++){
list.add(random.nextInt(100));
}
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
排序自定义类型元素
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
编译不通过的缘由:
Collections.sort(List list)该方法要求集合中的元素类型必须实现接口:
Comparable,该接口中有一个抽象方法compareTo,这个方法用来定义元素之间比较
大小的规则.所以只有实现了该接口的元素才能利用这个方法比较出大小进而实现排序
操作.
*/
Collections.sort(list);//编译不通过 compare比较 comparable可以比较的
System.out.println(list);
}
}
实际开发中,我们并不会让我们自己定义的类(如果该类作为集合元素使用)去实现Comparable接口,由于这对我们的程序有侵入性.
侵入性:当我们调用某个API功能时,其要求我们为其修改其他额外的代码,这个现象就是侵入性.侵入性越强的API越不利于程序的后期可维护性.应当尽量避免.
重载的Collections.sort(List list,Comparator c)方法
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
Collections.sort(List list)在排序List集合时要求集合元素必须实现了
Comparable接口。实现了该接口的类必须重写一个方法compareTo用与定义比较
大小的规则,从而进行元素间的比较后排序。否则编译不通过。
侵入性:
当我们调用某个API时,其反过来要求我们为其修改其他额外的代码,这种现象就
成为侵入性。侵入性不利于程序后期的维护,尽可能避免。
compare:比较
*/
// Collections.sort(list);
//匿名内部类的形式创建一个比较器
Comparator<Point> com = new Comparator<Point>() {
@Override
/**
* 实现比较器接口后必须重写方法compare.
* 该方法用来定义参数o1与参数o2的比较大小规则
* 返回值用来表明o1与o2的大小关系
*/
public int compare(Point o1, Point o2) {
int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
return len1-len2;
}
};
Collections.sort(list,com);//回调模式
System.out.println(list);
}
}
最终没有侵入性的写法
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
Collections.sort(List list)在排序List集合时要求集合元素必须实现了
Comparable接口。实现了该接口的类必须重写一个方法compareTo用与定义比较
大小的规则,从而进行元素间的比较后排序。否则编译不通过。
侵入性:
当我们调用某个API时,其反过来要求我们为其修改其他额外的代码,这种现象就
称为侵入性。侵入性不利于程序后期的维护,尽可能避免。
compare:比较
*/
// Collections.sort(list);
//匿名内部类的形式创建一个比较器
// Comparator<Point> com = new Comparator<Point>() {
// @Override
// /**
// * 实现比较器接口后必须重写方法compare.
// * 该方法用来定义参数o1与参数o2的比较大小规则
// * 返回值用来表明o1与o2的大小关系
// */
// public int compare(Point o1, Point o2) {
// int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
// int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
// return len1-len2;
// }
// };
// Collections.sort(list,com);//回调模式
// Collections.sort(list,new Comparator<Point>() {
// public int compare(Point o1, Point o2) {
// int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
// int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
// return len1-len2;
// }
// });
//lambda表达式
Collections.sort(list,(o1,o2)->
o1.getX() * o1.getX() + o1.getY() * o1.getY() -
o2.getX() * o2.getX() - o2.getY() * o2.getY()
);
System.out.println(list);
}
}
排序字符串
java中提供的类,如:String,包装类都实现了Comparable接口,但有时候这些比较规则不能满足我们的排序需求时,同样可以临时提供一种比较规则来进行排序.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortListDemo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// list.add("Tom");
// list.add("jackson");
// list.add("rose");
// list.add("jill");
// list.add("ada");
// list.add("hanmeimei");
// list.add("lilei");
// list.add("hongtaoliu");
// list.add("Jerry");
list.add("传奇");
list.add("小泽老师");
list.add("苍老师");
System.out.println(list);
//按照字符多少排序
// Collections.sort(list);
// Collections.sort(list, new Comparator<String>() {
// public int compare(String o1, String o2) {
//// return o1.length()-o2.length();
// return o2.length()-o1.length();//反过来减就是降序
// }
// });
Collections.sort(list,(o1,o2)->o2.length()-o1.length());
System.out.println(list);
}
}
5、小结
1)ArrayList底层实现是动态数组,所以遍历和随机访问元素的效率高,末尾插入数据实际跟LinkedList差不多,但如果是中间插入数据,要移动元素,导致数组重新分配,所以效率差,不适合快速插入和删除
2)而对LinkedList而言,插入元素,不管什么位置,这个开销是统一的,分配一个内部Entry对象,但是遍历或者随机访问元素,要移动指针查找,效率低。
3)二者都是线程不安全的,存放元素都是有序,不唯一。


