Collection
- Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的
List系列集合:List系列集合:ArrayList、LinkedList --java学习笔记-CSDN博客
Set系列集合:Set系列集合:Hashset、LinkedHashset、TreeSet --java学习笔记-CSDN博客
Collection集合体系特点
List系列集合:添加的元素是有序、可重复、有索引
- 有序:取出和存入时的顺序一致
- 可重复:可以往集合中添加多个一摸一样的数据
- 有索引:可以通过索引操作集合里面的数据
常见List系列集合—— ArrayList、LinkdList:有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引(与List系列集合相反)
- HashSet:无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:按照大小默认升序排序、不重复、无索引
Collection集合的常用方法
代码演示
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionTest1 {
public static void main(String[] args) {
Collection<String> arr = new ArrayList<>(); //多态写法
//1.public boolean add(E e):添加元素,添加成功返回true。
arr.add("aaa");
arr.add("bbb");
arr.add("ccc");
arr.add("aaa");
System.out.println(arr); //[aaa, bbb, ccc, aaa]
//2.public void clear():清空集合的元素。
arr.clear();
System.out.println(arr); //[]
// 3.public boolean isEmpty():判断集合是否为空 是空返回true,反之。
System.out.println(arr.isEmpty()); //true
arr.add("aaa");
System.out.println(arr.isEmpty()); //false
//4.public int size():获取集合的大小。
System.out.println(arr.size()); //1
//5.public boolean contains(object obj): 判断集合中是否包含某个元素。
System.out.println(arr.contains("aaa")); //true
System.out.println(arr.contains("bbb")); //false
// 6.public boolean remove(E e):删除某个元素:如果有多个重复元素默认删除前面的第一个!
arr.add("bbb");
arr.add("ccc");
arr.add("aaa");
arr.remove("aaa");
System.out.println(arr); //[aaa, bbb, ccc, aaa]
// 7.public 0bject[] toArray():把集合转换成数组
Object[] arr2 = arr.toArray();
System.out.println(Arrays.toString(arr2)); //[bbb, ccc, aaa]
String[] arr3 = arr.toArray(new String[0]);
System.out.println(Arrays.toString(arr3)); //[bbb, ccc, aaa]
//把一个集合的全部数据倒入到另一个集合中去
Collection<String> arr4 = new ArrayList<>();
arr4.add("aaa");
arr4.add("bbb");
Collection<String> arr5 = new ArrayList<>();
arr5.add("aaa");
arr5.add("bbb");
arr4.addAll(arr5);
System.out.println(arr4); //[aaa, bbb, aaa, bbb]
System.out.println(arr5); //[aaa, bbb]
}
}
运行结果
Collection集合的遍历方式
- 迭代器
- 增强for
- lambda表达式
迭代器
迭代器是用来遍历集合的专用方式(数组没有迭代器 ),在java中迭代器的代表是Iterator
Collection集合获取迭代器的方法:
Iterator迭代器中的常用方法:
代码演示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest2 {
public static void main(String[] args) {
Collection<String> arr = new ArrayList<>();
arr.add("愚者");
arr.add("正义");
arr.add("倒吊人");
arr.add("太阳");
arr.add("魔术师");
System.out.println(arr); //[愚者, 正义, 倒吊人, 太阳, 魔术师]
// 使用迭代器遍历集合
// 1.从集合对象中获取迭代器对象
Iterator<String> it = arr.iterator();
// System.out.println(it.next()); //愚者
// System.out.println(it.next()); //正义
// System.out.println(it.next()); //倒吊人
// System.out.println(it.next()); //太阳
// System.out.println(it.next()); //魔术师
// System.out.println(it.next()); // 出现异常 NoSuchElementException
//2.我们应该使用循环结合迭代器遍历集合
while(it.hasNext()){
String name = it.next();
System.out.println(name); //愚者\n 正义\n 倒吊人\n 太阳\n 魔术师\n
}
}
}
运行结果:
增强for循环
- 增强for循环可以用来遍历集合或者数组
- 增强for循环遍历集合,本质就是迭代器遍历集合的简化写法
代码演示:
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest3 {
public static void main(String[] args) {
Collection<String> arr = new ArrayList<>();
arr.add("愚者");
arr.add("正义");
arr.add("倒吊人");
arr.add("太阳");
arr.add("魔术师");
System.out.println(arr); //[愚者, 正义, 倒吊人, 太阳, 魔术师]
//使用增强for遍历集合或数组
for (String s : arr) {
System.out.println(s); //愚者\n 正义\n 倒吊人\n 太阳\n 魔术师\n
}
String[] names = {"小红","小白","小绿","小黑"};
for (String name : names) {
System.out.println(name); //小红\n 小白\n 小绿\n 小黑\n
}
}
}
运行结果:
Lambda表达式
- 得益于jdk 8开始的新技术Lambda表达式,提供了一种更简单、更直接的方式来遍历集合
需要使用Collection的如下方法来完成:
代码演示:
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest4 {
public static void main(String[] args) {
Collection<String> arr = new ArrayList<>();
arr.add("愚者");
arr.add("正义");
arr.add("倒吊人");
arr.add("太阳");
arr.add("魔术师");
System.out.println(arr); //[愚者, 正义, 倒吊人, 太阳, 魔术师]
//使用Lambda表达式遍历集合
//需要使用Collection的forEach方法来完成
// arr.forEach(new Consumer<String>() { //匿名内部类,可用Lambda表达式简化
// @Override
// public void accept(String s) {
// System.out.println(s); //愚者\n 正义\n 倒吊人\n 太阳\n 魔术师\n
// }
// });
// arr.forEach(s -> System.out.println(s)); //Lambda表达式,还可以简化成方法引用
arr.forEach(System.out::println); //方法引用
//愚者\n 正义\n 倒吊人\n 太阳\n 魔术师\n
}
}
运行结果:
集合的并发修改异常
- 使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误
案例:
import java.util.ArrayList;
import java.util.Collection;
public class CollectionTest5 {
public static void main(String[] args) {
Collection<String> arr = new ArrayList<>();
arr.add("愚者");
arr.add("愚人节");
arr.add("正义");
arr.add("太阳");
arr.add("魔术师");
System.out.println(arr);
Iterator<String> it = arr.iterator();
while(it.hasNext()){ //遍历每个元素
String name = it.next();
if(name.contains("愚")){ //删除带愚字的元素
arr.remove(name);
}
}
System.out.println(arr);
}
}
这一段代码乍一看没有任何问题,但是实际运行之后:
若是将增强for换成fori再看
运行结果
这次虽然没有报错,但是删除的元素少了一个,愚人节并没有被删掉。仔细思考不难发现,其实是因为在删除愚者的时候其它所有元素的索引都减了一,而i++到了索引1的位置,此时索引1已经是正义,也就跳过了愚人节元素,因此出现了bug。而迭代器(增强for本质就是使用迭代器)知道这个问题,它会直接抛个异常出来,在fori解决这个问题是很简单的,在删除的同时i--,或者把i++放到下面去,或者倒着删等等都可以解决这个问题,那么在迭代器中该如何解决呢?
很简单,在使用迭代器删除数据时不要使用集合对象自己去删除数据,那样是一定会出现并发修改异常的,而是使用迭代器本身提供的一个remove方法,这个remove方法的作用就是删除当前迭代到的数据,且再删除的同时做i--操作
运行结果:
增强for循环和lambda表达式删除数据也会出现并发修改异常,而且它们无法解决,因为增强for循环就是迭代器的简化写法,因为是简化写法所以无法拿到迭代器对象,也就不能使用迭代器的remove,而lambda式原理也是使用了增强for循环
Collection各集合应用场景
1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据
- 用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多
- 用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的
3.如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快
- 用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)
4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快
- 用LinkedHashSet集合(有序,不重复,无索引),底层基于哈希表和双链表
5.如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
- 用Treeset集合,基于红黑树实现
Collection的其它相关知识
可变参数:
用来操作集合的工具类Collections: