文章目录
Set
特点:
- Set是Collection的子接口
- Set数据结构是: 集合
- 有些子实现无序(
HashSet
), 有些子实现是有序的(LinkedHashSet
,TreeSet
大小有序) - 所有子实现都不允许存储重复元素(重复的定义是否一致)
- 有些子实现允许存储null(
HashSet
LinkedHashSet
), 有些子实现不允许存储null(TreeSet
)
Set的API
-------------------------set接口, 没有在Collection的基础上额外定义什么api---------
---------------------------------增删改查方法---------------------------------
boolean add(E e):
// 添加一个元素进入Collection
boolean addAll(Collection<? extends E> c):
// 添加一个Collection进指定的Collection
boolean remove(Object o):
// 删除元素, 只删除第一个出现的(如果存在多个)
boolean removeAll(Collection<?> c):
// 删除Collection中的所有存在的元素,会全部删除,如果存在多个
boolean contains(Object o):
// 判断是否存在指定元素
boolean containsAll(Collection<?> c):
// 判断给定的collection中是否全部存在于目标Collection
boolean retainAll(Collection<?> c):
// 将原有collection只保留传入的collection。
---------------------------------特殊方法---------------------------------
void clear():
// 清空collection
boolean equals(Object o) :
// 判断是否相等
int hashCode():
// 计算hashCode
boolean isEmpty():
// 是否为空
int size():
// collection里面的元素个数
---------------------------------方便遍历方法---------------------------------
Object[] toArray():
// 将collection转成一个数组,方便遍历,
<T> T[] toArray(T[] a):
// 类似,只是传入了一个数组
Iterator<E> iterator():
// 返回一个迭代器
Set中的HashSet、LinkedHashSet、TreeSet操作跟Map中的差不多
Stream
- 流是用来帮助我们简化集合操作的。
- 写法简单
- 代码极度的简化,但是可读性变差了
创建流
- 调用集合类的Stream方法,生成一个流(最常用/常见)
Collection collection = new ArrayList();
Stream stream = collection.stream();
- 由值创建
Stream<String> test = Stream.of("zs", "ls", "wu", "zl");
- 通过数组创建
String [] strs = {"zs", "ls", "wu"};
Stream<String> stream = Arrays.stream(strs);
中间操作
filter(过滤操作)
用于通过设置的条件过滤出元素
使用场景:
- 对元素进行过滤
eg:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("hello");
list.add("hi");
list.add("good");
Stream<String> stream = list.stream();
stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
if(s.equals("hello")){
return true;
}
return false;
}
}).collect(Collectors.toList());
}
}
-----> 转换为lambda表达式
/**
* 这里可以直接new这个接口,然后idea提示你怎么写
* 可以跟着idea一起走,它提示你就可以简化
* 需要注意: 一定要认识代码,如果不认识,退回去
*/
Stream<String> stream = list.stream();
stream.filter(s -> s.equals("hello")).collect(Collectors.toList());
注意: 每次中间操作会返回一个 Stream (可以有多次中间操作),这就允许对其操作可以像链条一样排列,变成一个管道。
- filter中的方法:
Stream<T> filter(Predicate<? super T> predicate);
public interface Predicate{}
// filter方法参数 ----> 需要传入的是一个 Predicate类型的实例。
// Predicate 里面只有一个方法。输入参数根据流里的数据确定,输出参数是个boolean
distinct(去重操作)
用于筛选元素(相当于去除重复元素)
使用场景:
- 对元素进行去重处理。底层是
LinkedHashSet
- 如果使用自定义的类,调用distinct,需要重写hashCode和equals方法
limit(截取操作)
用于获取指定数量(最大)的流。
使用场景:
StudentList.stream().filter(student -> student.getHeight > 180)
.limit(5)
.collect(Collectors.toList());
其中:
Stream<T> limit(long maxSize);
// limit(n)方法, 返回前n个元素.
// 如果流中有10个元素,limit(3) 则只返回3个元素。
// 如果流中有1个元素,limit(3) 则只返回1个元素。
skip(跳过操作)
skip(n)
方法,表示跳过前n个元素
Stream<T> skip(long n);
// skip(n)方法, 跳过前n个元素, 返回之后的元素. (如果整体不够n个, 返回空流)
sorted(排序操作)
用于对流进行排序
Stream<T> sorted();
// 自然顺序排序
Stream<T> sorted(Comparator<? super T> comparator);
// 提供一个比较器
eg:
List<Student> studentList = new StudentList().studentList;
studentList.stream().
filter(s -> s.getHeight() > 180)
.sorted((s1, s2) -> s1.getHeight() - s2.getHeight())
.collect(Collectors.toList());
map(转换操作)
用于映射每个元素到对应的结果
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
// TODO: map映射返回新的数据, map的参数是一个方法
// map主要是把一种类型转换成另外一种类型
// map在工作过程中,常用
eg:
List<Student> studentList = new StudentList().studentList;
List<String> collect = studentList.stream()
.map(student -> student.getName())
.collect(Collectors.toList());
System.out.println(collect);
终止操作
anyMatch(是否有任意一个匹配)
检查流到最后的数据, 是否有一个/多个数据匹配某种情况
boolean anyMatch(Predicate<? super T> predicate);
// anyMatch: 判断该stream中的所有元素, 是否存在某个/某些元素,可以根据某个条件处理之后, 满足true
eg:
boolean b = studentList.stream()
.filter(s -> s.getHeight() > 190)
.anyMatch(a -> {
return a.getAddress() == Student.Address.BJ;
});
System.out.println(b);
allMatch(是否所有的全匹配)
检查是否所有元素都匹配
boolean allMatch(Predicate<? super T> predicate);
// allMatch: 判断该stream中的所有元素, 是否所有元素 可以根据某个条件处理之后, 满足true
eg:
boolean b = studentList.stream().filter(s -> s.getHeight() >= 200)
.allMatch(s -> s.getAddress() == Student.Address.SH);
System.out.println(b);
noneMatch(没有匹配)
检查是否没有匹配元素
boolean noneMatch(Predicate<? super T> predicate);
// noneMatch: 判断该stream中的所有元素, 是否所有元素 可以根据某个条件处理之后, 满足false
eg:
boolean b1 = studentList.stream()
.noneMatch(s -> Student.Address.SZ.equals(s.getAddress()));
System.out.println(b1);
findAny(找到任意一个)
返回流中任意元素:默认第一个
Optional<T> findAny();
// findAny: 返回任意元素(默认第一个)
eg:
List<Student> studentList = new StudentList().studentList;
Optional<Student> any = studentList.stream()
.findAny();
//TODO: 注意, Optional作为一个容器代表一个值存在或者不存在
//TODO: Optional中存在几个方法, 可以让使用者显式的检查值存在或者不存在
// <1>: isPresent()方法: 如果 Optional包含值返回true, 否则返回false
// <2>: ifPresent(代码块)方法: 会将Optional包含的值, 传给指定的代码块
// <3>: get()方法: 如果Optional包含值, 返回包含的值, 如果没有数据则抛出异常
// <4>: orElse(默认值): 如果Optional包含值, 返回包含的值, 否则返回默认值
any.isPresent();
any.ifPresent(a -> System.out.println(a));
any.get();
使用流程:
- 需要判断一下这个
optional
里面有没有元素 - 如果有,直接拿数据
findFirst(找到第一个)
返回第一个元素
Optional<T> findFirst();
// findFirst: 返回第一个元素
eg:
Optional<Student> any = studentList.parallelStream()
.sorted((o1, o2) -> o1.getAge() - o2.getAge()).findFirst();
if (any.isPresent()) {
Student student = any.get();
System.out.println(student);
}
forEach(遍历流)
void forEach(Consumer<? super T> action);
// forEach: 遍历元素(void方法)
eg:
studentList.stream()
.filter(student -> student.getHeight() > 180)
.forEach(student -> System.out,println(student));
count(返回元素中数量)
long count();
// count: 计算元素个数
eg:
long count = studentList.stream()
.filter(a -> a.getAddress() == Student.Address.BJ)
.count();
System.out.println(count);
reduce(按照一定规则减少数据)
将参加计算的元素按照某种方式减少。
比如:两两比较,返回较大的 —> 会拿到里面的最大值;
或者两两比较,返回较小的 —> 最终会拿到最小值
TODO: 规约 reduce
<1>一参情况: Optional<T> reduce(BinaryOperator<T> accumulator)
<2>二参情况: T reduce(T identity, BinaryOperator<T> accumulator);
<1>参数:
// 返回值类型为Optional, 是应对如果流中没有任何元素情况(这种情况没有初始值就无法返回结果)
// 所以1参是把结果包裹在一个Optional对象里(可以通过get方法获取),用以表明/处理结果可能不存在情况
<2>参数:
// BinaryOperator: 将两个元素合起来产生一个新值
// identity: 计算的初始值/起始值(用来和第一个元素计算结果)
eg:
// 计算年龄的总和
Optional<Integer> optional = studentList.stream()
.map(a -> a.getAge())
.reduce((a, b) -> a + b);
Integer sum = optional.get();
System.out.println(sum);
List<Student> studentList = new StudentList().studentList;
// 年龄最大的学生
Optional<Integer> reduce2 = studentList.stream().map(a -> a.getAge()).reduce((a, b) -> {
if (a > b) {
return a;
}
return b;
});
Optional<Integer> reduce3 = studentList.stream().map(a -> a.getAge()).reduce(Integer::max);
// 年龄最小的学生
Optional<Integer> reduce4 = studentList.stream().map(a -> a.getAge()).reduce((a, b) -> {
if (a > b) {
return b;
} else {
return a;
}
});
Optional<Integer> reduce5 = studentList.stream().map(a -> a.getAge()).reduce(Integer::min);
collect(收集器)
用于收集数据经过流计算的结果
Collectors:收集,作用是将元素分别归纳进可变容器 List
、Map
、Set
、Collection
或者ConcurrentMap
Collectors.toList()
Collectors.toCollection()
Collectors.toSet()
Collectors.toMap()
注意:
// Collection 没有直接实现的子类
LinkedList<Student> collect = studentList.stream()
.filter(a -> a.getAddress() == Student.Address.WH)
.collect(Collectors.toCollection(() -> new LinkedList<>()));
// toMap
Map<String, Integer> collect1 = studentList.stream()
.filter(a -> a.getAddress() == Student.Address.WH)
.collect(Collectors.toMap(Student::getName, student -> student.getAge()));
// toMap中的去重
Map<String, Student> collect = studentList.stream()
.filter(student -> Student.getAddress().equals("beijing"))
.collect(Collection.toMap(student -> student.getAge(), student -> student
, (student, student2) -> student));
// 第三个参数代表,当我的key重复的时候,需要告诉我合并value的规则