1.Collection接口
Collection接口是List
、Set
和Queue
接口的父接口,该接口里定义的方法既可以用于操作List、Set也可以用于操作Queue集合
Collection接口常用方法
Collection方法可参考API
boolean add(Object o):添加元素,如果集合对象被添加操作改变了则返回true
boolean addAll(Collection c):将集合A的元素添加到集合B中,如果集合对象被添加操作改变了则返回true
void clear():清除集合里的所有元素怒,清除后集合的长度为0
boolean concation(Object obj):返回集合里是否包含指定元素
boolean concationAll(Collection c):返回集合A里是否包含集合B里的所有元素
boolean isEmpty():判断集合是否为空,如果长度为0返回true,否则返回false,null则会报空指针异常
Iterator iterator():返回一个Iterator对象,用于遍历集合里的所有元素
boolean remove(Object obj):删除集合中指定元素,如果存在重复元素,只删除第一个符合条件的元素
boolean removeAll(Collection c):从集合A中删除集合B里包含的所有元素,如果集合A删除了集合B中的一个或多个元素则返回true
int size():返回集合的元素个数
Object[] toArray():可以将一个集合转换为一个数组,所有的集合元素变成对应的数组元素
Collection接口新增方法
removeIf(Predicate filter):批量删除符合filter条件的所有元素
List list=new ArrayList();
list.add("10");
list.add("java");
list.add("Hadoop");
list.add("Spark");
list.add("这是一个呆逼的代码");
list.add("如果非要有一个人赢,那这个人为什么不是我");
list.removeIf(ele->ele.equals("java"));
list.removeIf(ele->((String)ele).contains("如果"));
list.removeIf(ele->((String)ele).length()<=5);
for (Object o : list) {
Object obj=o;
System.out.println("for:"+obj);
}
执行结果:
for:Hadoop
for:这是一个呆逼的代码
上述方法中涉及到一个Iterator接口可以遍历集合元素,来自于Collection接口的父接口Iterable
1.1 遍历集合的方式
-
迭代器遍历
使用Iterator参考: -
Lambda表达式遍历
父接口在JDK8提供了一个默认方法forEach(),可采用lambda表达式对集合直接进行遍历,不用使用迭代器了,该Lambda表达式的目标类型是Consumer//父类Iterable的forEach()方法遍历集合中的元素 list.forEach(obj-> System.out.println("迭代集合元素:"+obj));
-
for循环
//for循环遍历 for (Object o : list) { Object obj=o; System.out.println("for:"+obj); }
-
转换为数组再遍历
//转换为数组后遍历集合中的元素 Object[] objects = list.toArray(); for (Object object : objects) { System.out.println("数组遍历:"+object); }
1.2 Stream操作集合
IntStream is=IntStream.builder().add(10).add(13).add(20).add(70).build();
//以下方法只能使用一次,使用后将会自动关闭流:java.lang.IllegalStateException: stream has already been operated upon or closed
// System.out.println("is中所有元素中最大值:" + is.max().getAsInt());
// System.out.println("is中所有元素中最小值:" + is.min().getAsInt());
// System.out.println("is中所有元素总和:" + is.sum());
// System.out.println("is中所有元素平均值:" + is.average());
// System.out.println("is中所有元素平方大于20:" + is.allMatch(ele->ele*ele>20));
// System.out.println("is中包含任何一个或多个元素的平方大于20:" + is.anyMatch(ele->ele*ele>20));
// System.out.println("is中包含任何一个或多个元素的平方大于20:" + is.anyMatch(ele->ele*ele>20));
System.out.println("***************************************")
//将原IntStream流集合中的所有数据*2+1
IntStream intStream = is.map(ele -> ele * 2 + 1);
intStream.forEach(ele-> System.out.println(ele));
常用方法:
中间方法:
filter(Predicate predicate):过滤Stream中所有不符合predicate的元素
mapToXxx(ToXxxFuncation mapper):使用ToXxxFunction对流中的元素执行一对一的转换,该方法返回的新流中包含了ToXxxFunction转换生成的所有元素。
peek(Consumer action):依次对每个元素执行一些操作,该方法返回的流与原有流中包含相同的元素,该方法主要用于调试
distinct():该方法用于排序流中的所有重复的元素,实际还是使用equals方法
sorted():该方法用于保证流的后续访问中最大允许访问的元素个数,这是一个有状态的、会短路的方法
末端方法:
forEach(Consumer action):遍历流中所有元素,对每个元素执行action
toArray():将流中所有元素转换为数组
reduce():该方法有三个重载的版本,都是用于通过某种操作来合并流中的元素
min():返回流中所有元素的最小值
max():返回流中所有元素的最大值
count():返回流中所有元素的数量
anyMatch(Predicate predicate):判断流中是否至少包含一个元素符合Predicate的条件
allMatch(Predicate predicate):判断流中是否所有元素都符合Predicate的条件
noneMatch(Predicate predicate):判断流中是否所有元素都不符合Predicate的条件
findFirst():返回流中的第一个元素
findAny():返回流中的任意一个元素
除了使用创建流的方式来操作集合,在JDK8开始,在Collection接口中添加了stream()默认方法,该方法可以返回该集合对应的流
Stream stream = list.stream();
System.out.println(stream.findFirst().get());
重点:所有对于集合的流操作,只能使用一次,如果第二次使用就会报错java.lang.IllegalStateException: stream
在集合中添加的对象一定要重写equals方法,否则后续对集合数据的操作如果涉及到比较,不重写就会去调用Object类中的equals方法–等价于==
,重写后才是比较内容
1.3 List集合
ArrayList和Vector实现类
-
ArrayList实现类是线程不安全的,Vector实现类是线程安全的,但是Vector本身存在很多缺点,开发中不使用
-
如果存在需要使用线程安全的集合,可以使用Collections工具类,将ArrayList变成线程安全的
-
Vector提供了一个Stack子类,类似于栈的数据结构,但是出栈和进栈都是Object类型的,因此,从栈中取出元素的时候必须进行类型转换–这种也抛弃了,如果要使用可以使用ArrayDeque(实现了List接口和Deque接口,底层也是基于数组的)
总结List的性能
-
List实际上就是一个线性表的接口
-
ArrayList、LinkedList是线性表的典型实现
-
Queue代表了队列、Deque代表了双端队列
-
选择:
-
随机访问–遍历等选择底层为数组的:ArrayList/Vector
-
频繁增删的选择底层是链表的:LinkedList–因为ArrayList和Vector需要频繁扩容,且插入后大量数据要相继后移或前移
-
ArrayList和Vector之间尽可能选择ArrayList,即使需要线程安全的条件也可以使用工具类Collections来对ArrayList对象进行线程同步
-
ArrayList和Vector遍历尽量使用get()方法获取元素–这样性能更好;
-
LinkedList遍历尽量使用Iterator迭代器进行遍历
-
1.4Set接口
总结Set的性能
-
HashSet的性能总是比TreeSet的性能好,特别是添加查询等操作时
- 因为TreeSet需要额外的红黑树来维护集合元素的次序,只有当需要一个保持排序的Set时才使用TreeSet
-
HashSet和LinkedHashSet进行比较
-
插入删除操作,HashSet性能高于LinkedHashSet,这是因为维护了链表带来的开销
-
遍历集合LinkedHashSet的性能高于HashSet
-
-
EnumSet是Set集合中性能最好的,但是只能保存相同的枚举类的枚举值作为集合元素
-
Set集合都是非线程安全的,如果涉及多线程问题,必须在创建实例时就进行同步操作
SortedSet s=Collections.synchronizedSortedSet(new TreeSet());