集合类概述
1.继承树
2.集合和数组
区别如下:
- 数组可以存储基本数据类型,也可以存储引用类型;而集合只能存储引用类型(比如存储int,它会自动装箱成Integer)
- 数组长度固定,集合长度可变
3.List和map
- 相同
- 都是集合类,都是接口
- 区别
- List存储单列元素,Map存储键值对
- List允许元素重复,Map不允许key重复(重复则覆盖)
- List存储有序,Map存储无序
- 无论是List还是Map,它们实现动态增长都是有性能消耗的。在初始化集合的时候先估算数据量并分配合理的容量会减少动态增长时的消耗。
4.Collection基础功能
Collection接口定义的操作集合的方法有:
- int size()
- boolean add(Object o)
- boolean addAll(Collection c)
- void clear()
- boolean contains(Object o)
- boolean containsAll(Object o)
- Iterator iterator()
- boolean isEmpty()
- boolean remove(Object o)
- boolean removeAll(Collection c)
- boolean retainAll(Collection c)
- Object[] toArray()
集合遍历
1.forEach方法
Java8为Iterator接口新增的forEach默认方法
import java.util.Collection;
import java.util.HashSet;
public class CollectionTest {
public void each() {
Collection<String> books = new HashSet<>();
books.add("aaaaaa");
books.add("bbbbbb");
//1.使用Collection提供的方法
books.forEach(str -> System.out.println(str));
2.使用迭代器Iterator
每个集合都以内部类的方式实现了Iterator接口,Iterator替代了Enumeration,其更加安全,因为其遍历集合时会阻止其他线程修改集合
ListIterator继承了Iterator接口,它用于遍历List集合的元素,由于是双向遍历,不仅可以删除元素,还可以添加和修改元素
Java8增强的Iterator提供的方法如下:
-
boolean hasNext()
-
Object next()
-
void remove()
-
void forEachRemaining(Consumer action)
//2使用iterator的方法 Iterator<String> iterator = books.iterator(); while (iterator.hasNext()) { //需要强制转换 String str = (String) iterator.next(); if("aaaaaa".equals(str)) iterator.remove(); } //3.使用lambda表达式遍历 iterator.forEachRemaining(str -> System.out.println(str)); } }
集合过滤
- Java8为Collection新增的removeIf(Predicate filter)方法,可以批量删除符合filter条件的元素。使用lambda表达式做参数表述为
books.removeIf(str -> ((String)str).length() < 10);
- 使用Java8新增的Stream流来操作集合
- 包含Stream、InStream、LongStream、DoubleStream等流式API,独立使用步骤如下:
public void stream() {
//1.使用流的builder类方法创建对应的Builder
//2.重复调用add()方法向流中添加元素
//3.调用builder的build()方法获取对应的Stream
IntStream is = IntStream.builder()
.add(1)
.add(2)
.add(3)
.add(5)
.build();
//4.调用Stream的聚集方法(很多),每次只能调用一个,调用完流即不可用
//如System.out.println(is.sum());
//将is映射成新的newIs流
IntStream newIs = is.map(ele -> ele * 2 + 1);
//使用方法引用的方式遍历集合元素
newIs.forEach(System.out::println);
}
- 使用Collection接口提供的stream()默认方法,返回对应集合的流,进而进行聚集操作,简化了集合编程。使用如下:
public void preStream() {
Collection<String> books = new HashSet<>();
books.add("java");
books.add("myjava");
books.add("JAVA");
System.out.println(books.stream().filter(ele -> ((String)ele).contains("java")).count());
//1.先调用Collection对象的stream方法将集合转换为Stream
//2.再调用Stream的mapToInt方法获取原有的Stream对应的IntStream
//3.再调用forEach方法遍历IntStream中的元素
books.stream().mapToInt(ele -> ((String)ele).length()).forEach(System.out::println);
}
fail-fast机制
- 简介
fail-fast机制是java容器(Collection和Map都存在fail-fast机制)中的一种错误机制。在遍历一个容器对象时,当容器结构被修改(remove方法除外),很有可能会抛出ConcurrentModificationException,产生fail-fast。 - 原理
每次初始化一个迭代器都会执行int expectedModCount = modCount;
,modCount表示修改次数,迭代器会通过checkForComodification()方法判断modCount和expectedModCount 是否相等,如果不相等就表示已经有线程修改了集合结构。 - 如何避免
使用java.util.concurrent包下的类去取代java.util包下的类。Java1.5并发包含有线程安全集合类,允许在迭代时修改集合,比如ConcurrentHashMap。