Collection是单列集合类的根接口,用于存储符合某种规则的元素。
List集合中允许出现重复的元素,所有元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。即List集合元素是有序可重复的。
①AbstractList抽象类:此类提供 List 接口的骨干实现,以最大限度地减少实现“随机访问”数据存储(如数组)支持的该接口所需的工作。
②ArrayList类:List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。
③Linklist类:List 接口的双向链表的实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
④Vector类:(AbstractList的子类)可以实现可增长的对象数组,与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector的大小可以根据需要增大或缩小,以适应创建Vector后进行添加或移除项的操作。
⑤Stack类:(Vector的子类)Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。
Stack类的pop和peek方法的区别:
pop()返回栈顶的元素,并将该栈顶的元素弹出栈 peek()返回栈顶的元素,但不弹出该栈顶元素
一、ArrayList集合
在ArrayList内部封装了一个长度可变的数组对象,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此ArrayList可以看做是一个长度可变的数组。
(1)通过add()方法和get()方法实现元素的存取(可以存入重复的值)。用remove()方法删除指定位置的元素。用set()方法修改指定位置的元素,索引号从0开始到size-1。
public void demo1() {
List<String> list = new ArrayList<>();
list.add("王侃");
list.add("李里");
list.add("王计");
list.add("李里");
list.add(3, "甜为");//添加到指定位置,索引从0开始
System.out.println(list);
int size = list.size();//获取集合中元素的个数
System.out.println("集合元素的个数是:"+size);
String str = list.get(0);//取出索引号是0的元素
System.out.println("索引号为0的元素是"+str);
list.remove(1);//删除索引号为1的元素
list.set(2, "袖敌");//将索引号为2的元素修改成"袖敌"
for(String i:list) {//foreach循环遍历数组
System.out.print(i+" ");
}
System.out.println();
boolean b = list.isEmpty();//判断集合是否为空
System.out.println("集合是否为空:"+b);
list.clear();//清空集合
System.out.println("清空后的集合:"+list);
}
运行结果:
[王侃, 李里, 王计, 甜为, 李里]
集合元素的个数是:5
索引号为0的元素是王侃
王侃 王计 袖敌 李里
集合是否为空:false
清空后的集合:[]
(2)使用Iterator迭代器对集合中的元素进行迭代输出。
使用Collections的sort()方法对集合进行升序排列。
public void c() {
List<Integer>list = new ArrayList<>();
for(int i = 0;i<10;i++) {//随机产生集合元素
int num = (int)(Math.random()*20+1);
list.add(num);
}
Iterator<Integer> it = list.iterator();//使用Iterator迭代器
while(it.hasNext()) {
Integer number = it.next();
System.out.print(number+" ");
}
System.out.println();
Collections.sort(list);//对集合进行升序排列
System.out.println(list);
}
运行结果:
1 5 15 18 13 19 10 5 8 4
排序后的集合元素:[1, 4, 5, 5, 8, 10, 13, 15, 18, 19]
(3)去掉ArrayList中自定义类的重复对象元素:
①创建一个新的集合
②遍历旧集合中的每一个元素,在新集合中找这个元素,如果不存在,就添加到新集合中(需要在自定义类中重写equals()方法,写出 去重 的规则。因为我们使用contains()方法判断旧集合中的元素是否在新集合中存在,contains()方法的底层依赖是equals()方法,所以需要重写equals()方法定义去掉重复元素的规则)
例:
public class Demo{
public void a() {
List<Student> list = new ArrayList<>();
Student d1 = new Student(1, "老父子", 78);
Student d2 = new Student(2, "夏天", 16);
Student d3 = new Student(3, "牛犇", 24);
Student d4 = new Student(4, "易然", 34);
Student d5 = new Student(5, "幕辞", 22);
Student d6 = new Student(1, "薛弩", 19);
list.add(d1);
list.add(d2);
list.add(d3);
list.add(d4);
list.add(d5);
list.add(d6);
System.out.println(list);
//创建一个新集合
List<Student> newList = new ArrayList<Student>();
//遍历旧集合
Iterator it = list.iterator();
while(it.hasNext()){
Student s = (Student)it.next();
if(!newList.contains(s)){
newList.add(s);//把没在新集合中的元素添入新集合
}
}
//遍历新集合
System.out.println("去重后的新集合为:");
for(Student i:newList) {
System.out.println(i);
}
}
public static void main(String[] args) {
new Demo().a();
}
}
运行结果:
[Student [id=1, name=老父子, age=78], Student [id=2, name=夏天, age=16], Student [id=3, name=牛犇, age=24], Student [id=4, name=易然, age=34], Student [id=5, name=幕辞, age=22], Student [id=1, name=薛弩, age=19]]
去重后的新集合为:
Student [id=1, name=老父子, age=78]
Student [id=2, name=夏天, age=16]
Student [id=3, name=牛犇, age=24]
Student [id=4, name=易然, age=34]
Student [id=5, name=幕辞, age=22]
(4)对自定义类的元素进行排序
需要实现Comparable接口,并重写comparaTo()方法定义排序的规则。例:
public class Demo2{
public void a() {
List<Student> list = new ArrayList<>();
Student d1 = new Student(1, "老父子", 78);
Student d2 = new Student(2, "夏天", 16);
Student d3 = new Student(3, "牛犇", 24);
Student d4 = new Student(4, "易然", 34);
Student d5 = new Student(5, "幕辞", 22);
Student d6 = new Student(6, "薛弩", 19);
list.add(d1);
list.add(d2);
list.add(d3);
list.add(d4);
list.add(d5);
list.add(d6);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
public static void main(String[] args) {
new Demo().a();
}
}
运行结果:
[Student [id=1, name=老父子, age=78], Student [id=2, name=夏天, age=16], Student [id=3, name=牛犇, age=24], Student [id=4, name=易然, age=34], Student [id=5, name=幕辞, age=22], Student [id=6, name=薛弩, age=19]]
排序后的元素:
[Student [id=2, name=夏天, age=16], Student [id=6, name=薛弩, age=19], Student [id=5, name=幕辞, age=22], Student [id=3, name=牛犇, age=24], Student [id=4, name=易然, age=34], Student [id=1, name=老父子, age=78]]
自定义的Student类
public class Student implements Comparable<Student>{//实现Comparable
private Integer id;
private String name;
private Integer age;
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
//重写equals()方法
public boolean equals(Object obj) {
Student other = (Student) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
//重写comparaTo()方法
public int compareTo(Student o) {
return this.getAge()-o.getAge();//按照年龄大小进行排序
}
}
二、LinkedList集合
LinkedList结合内部维护了一个双向循环链表,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素,从而可以将所有的元素彼此连接起来。当插入一个新元素的时候只需要i修改元素之间的这种引用关系即可,删除一个元素也是相同的。因为这样的存储结构,所以LinkedList集合对于增删操作的效率很高。相比较ArrayList,在增删元素时效率很低,在查询元素时速度很快。
(1)LinkedList集合一些基本方法
利用add()和get()方法进行存取元素,remove()方法删除指定元素
public void a() {
LinkedList<String> list = new LinkedList<>();
list.add("小红");
list.add("小兰");
list.add("小紫");
list.addFirst("老大");//在首部添入元素
list.addLast("最小");//在尾部添入元素
list.add(2, "小橙");//在指定位置添入元素
System.out.println(list);
int size = list.size();//集合中元素长度
System.out.println("集合中元素的长度为:"+size);
String str1 = list.get(2);//获取索引号为2的元素内容
String str2 = list.getFirst();//获取第一个元素的内容
String str3 = list.getLast();//获取最后一个元素的内容
System.out.println("索引号为2的元素是:"+str1);
System.out.println("第一个元素是:"+str2);
System.out.println("最后一个元素是:"+str3);
list.remove(2);//删除索引号为2的元素
list.removeFirst();//删除第一个元素
list.removeLast();删除最后一个元素
System.out.println("删除后的集合为:“);
Iterator<String> it = list.iterator();//利用迭代器
while(it.hasNext()) {
String str = it.next();
System.out.print(str+" ");
}
}
运行结果:
[老大, 小红, 小橙, 小兰, 小紫, 最小]
集合中元素的长度为:6
索引号为2的元素是:小橙
第一个元素是:老大
最后一个元素是:最小
删除后的集合为:
小红 小兰 小紫
(2)去掉ListedList中自定义类的重复对象元素:
(和ArrayList是相同的)
①创建一个新的集合
②遍历旧集合中的每一个元素,在新集合中找这个元素,如果不存在,就添加到新集合中(需要在自定义类中重写equals()方法,写出 去重 的规则。因为我们使用contains()方法判断旧集合中的元素是否在新集合中存在,contains()方法的底层依赖是equals()方法,所以需要重写equals()方法定义去掉重复元素的规则)
例:
public void b() {
LinkedList<Student> list = new LinkedList<>();
Student stu1 = new Student(1,"小红",15);
Student stu2 = new Student(2,"小绿",23);
Student stu3 = new Student(3,"小蓝",34);
Student stu4 = new Student(4,"小橙",45);
Student stu5 = new Student(5,"小紫",57);
Student stu6 = new Student(5,"小灰",67);
list.add(stu1);
list.add(stu2);
list.add(stu3);
list.add(stu4);
list.add(stu5);
list.add(stu6);
System.out.println(list);
//创建一个新集合
LinkedList<Student> newList = new LinkedList<Student>();
//遍历旧集合
Iterator it = list.iterator();
while(it.hasNext()){
Student s = (Student)it.next();
if(!newList.contains(s)){
newList.add(s);//把没在新集合中的元素添入新集合
}
}
for(Student i:newList) {
System.out.println(i);
}
}
运行结果:
[Student [id=1, name=小红, age=15], Student [id=2, name=小绿, age=23], Student [id=3, name=小蓝, age=34], Student [id=4, name=小橙, age=45], Student [id=5, name=小紫, age=57], Student [id=5, name=小灰, age=67]]
Student [id=1, name=小红, age=15]
Student [id=2, name=小绿, age=23]
Student [id=3, name=小蓝, age=34]
Student [id=4, name=小橙, age=45]
Student [id=5, name=小紫, age=57]
(3)对自定义类的元素进行排序
需要实现Comparable接口,并重写comparaTo()方法定义排序的规则。例:
public void demo() {
LinkedList<Student> list = new LinkedList<>();
Student stu1 = new Student(1,"小红",35);
Student stu2 = new Student(2,"小绿",23);
Student stu3 = new Student(3,"小蓝",11);
Student stu4 = new Student(4,"小橙",45);
Student stu5 = new Student(5,"小紫",97);
Student stu6 = new Student(6,"小灰",67);
list.add(stu1);
list.add(stu2);
list.add(stu3);
list.add(stu4);
list.add(stu5);
list.add(stu6);
System.out.println(list);
Collections.sort(list);
System.out.println("排序后的元素:");
System.out.println(list);
}
运行后的结果:
[Student [id=1, name=小红, age=35], Student [id=2, name=小绿, age=23], Student [id=3, name=小蓝, age=11], Student [id=4, name=小橙, age=45], Student [id=5, name=小紫, age=97], Student [id=6, name=小灰, age=67]]
排序后的元素:
[Student [id=3, name=小蓝, age=11], Student [id=2, name=小绿, age=23], Student [id=1, name=小红, age=35], Student [id=4, name=小橙, age=45], Student [id=6, name=小灰, age=67], Student [id=5, name=小紫, age=97]]
三、ArrayList和LinkList的区别
(1)ArrayList和LinkedList,ArrayList是一个动态数组,LinkedList是一个双向链表结构,都是实现了List接口;
(2)当随机访问集合中的元素时,ArrayList比LinkedList的效率高,因为LinkedList时线性的数据存储方式,需要移动指针从前往后一次查找;
(3)当对集合元素进行增删操作时,LinkedList比ArrayList效率高,因为ArrayList是数组,所以在进行增删操作时,会对操作点之后的所有元素的下标索引造成影响,需要进行元素的移动;
(4)从利用效果来讲:ArrayList自由性比较低,需要设置固定大小容量,但是使用比较方便,只需要创建然后添加元素,通过下标索引进行使用。而LinkedList自由性较高,可以动态的随元素的变化而变化,但是不便于使用;
(5)ArratList需要在List列表预留一定空间;而LinkedList需要存储结点信息以及结点指针信息。