目录
distinct去除重复元素 -- 依赖hashcode和equals方法
JDK8 以后提供了Stream流来对集合进行处理,配合lambda表达式简化code,带来函数式编程
Stream流的核心思想:
- 先得到集合或者数组的Stream流(就是一根传送带)
- 把元素放上去
- 然后就用这个Stream流简化的API来方便的操作元素。
Stream流可以分为三部分:
- 获取Stream流
--创建一条流水线,并把数据放到流水线上准备进行操作 - 中间方法
--流水线的操作,一次操作完毕后,还可以继续进行其他操作 - 终结方法
--一个Stream流只能有一个终结方法,是流水线上的最后一个操作
Stream流的获取方式
Collection接口(List & Set)
名称 | 说明 |
default Stream<E> stream() | 获取当前集合对象的Stream流 |
/** --------------------Collection集合获取流------------------------------- */
Collection<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
Collection<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
Map接口
/** --------------------Map集合获取流------------------------------- */
Map<String, Integer> maps = new HashMap<>();
// 键流
Stream<String> keyStream = maps.keySet().stream();
// 值流
Stream<Integer> valueStream = maps.values().stream();
// 键值对流(拿整体)
Stream<Map.Entry<String,Integer>> keyAndValueStream = maps.entrySet().stream();
数组
/** ---------------------数组获取流------------------------------ */
String[] names = {"赵敏","小昭","灭绝","周芷若"};
Stream<String> nameStream = Arrays.stream(names);
Stream<String> nameStream2 = Stream.of(names);
中间方法
注意:
l 中间方法也称为非终结方法,调用完成后返回新的 Stream 流可以继续使用,支持链式编程。l 在 Stream 流中无法直接修改集合、数组中的数据。
filter过滤
名称 | 说明 |
Stream<T> filter(Predicate<? super T> predicate) | 用于对流中的数据进行过滤。 |
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张三丰");
// Stream<T> filter(Predicate<? super T> predicate)
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
long size = list.stream().filter(s -> s.length() == 3).count();
System.out.println(size);
limit前几个元素
名称 | 说明 |
Stream<T> limit(long maxSize) | 获取前几个元素 |
// list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println);
Skip跳过前几个元素
名称 | 说明 |
Stream<T> skip(long n) | 跳过前几个元素 |
list.stream().filter(s -> s.startsWith("张")).skip(2).forEach(System.out::println);
distinct去除重复元素 -- 依赖hashcode和equals方法
名称 | 说明 |
Stream<T> distinct() | 去除流中重复的元素。依赖(hashCode和equals方法) |
list.stream().filter(s -> s.startsWith("张")).distinct().forEach(s -> System.out.println(s));
max取最大值
需要比较器 Comparator
List<Employee> one = new ArrayList<>();
one.add(new Employee("猪八戒",'男',30000 , 25000, null));
one.add(new Employee("孙悟空",'男',25000 , 1000, "顶撞上司"));
one.add(new Employee("沙僧",'男',20000 , 20000, null));
one.add(new Employee("小白龙",'男',20000 , 25000, null));
Employee e = one.stream().max((e1, e2) -> Double.compare(e1.getSalary() + e1.getBonus(), e2.getSalary() + e2.getBonus())).get();
Sort排序
需要比较器 Comparator
List<Employee> one = new ArrayList<>();
one.add(new Employee("猪八戒",'男',30000 , 25000, null));
one.add(new Employee("孙悟空",'男',25000 , 1000, "顶撞上司"));
one.add(new Employee("沙僧",'男',20000 , 20000, null));
one.add(new Employee("小白龙",'男',20000 , 25000, null));
one.stream().sorted((e1, e2) -> Double.compare(e1.getSalary() + e1.getBonus(), e2.getSalary() + e2.getBonus()))
.forEach(s -> System.out.println(s));
Map对数据进行加工
参数为Function<K,V>
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","张三丰","赵敏","小昭","张强");
list.stream().map(new Function<String, String>() {
@Override
public String apply(String s) {
return "黑马的:" + s;
}
}).forEach(System.out::println);
//等同于上面, lambda简写格式
list.stream().map(s -> "黑马的:" + s).forEach(a -> System.out.println(a));
//相当于Function<String,Student>
list.stream().map(s -> new Student(s)).forEach(s -> System.out.println(s));
//上一行的简化格式
list.stream().map(Student::new).forEach(System.out::println);
contact 合并两个流为一个流
名称 | 说明 |
static <T> Stream<T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
Stream<String> s2 = Stream.of("java1", "java2");
// public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
Stream<String> s3 = Stream.concat(s1 , s2);
总结方法
注意:终结操作方法,调用完成后流就无法继续使用了,原因是不会返回Stream了。
forEach 遍历
名称 | 说明 |
void forEach(Consumer action) | 对此流的每个元素执行遍历操作 |
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张三丰");
// Stream<T> filter(Predicate<? super T> predicate)
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
count 元素个数
名称 | 说明 |
long count() | 返回此流中的元素数 |
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张三丰");
long size = list.stream().filter(s -> s.length() == 3).count();
System.out.println(size);
Collect 收集方法
toList
名称 | 说明 |
public static <T> Collector toList() | 把元素收集到List集合中 |
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张三丰");
Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
List<String> zhangList = s1.collect(Collectors.toList()); // 可变集合
toSet
名称 | 说明 |
public static <T> Collector toSet() | 把元素收集到Set集合中 |
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰","张三丰");
// 注意注意注意:“流只能使用一次”
Set<String> zhangSet = list.stream().filter(s -> s.startsWith("张"))
.collect(Collectors.toSet());
System.out.println(zhangSet);
toMap
名称 | 说明 |
public static <T> Collector toMap(Function keyMapper , Function valueMapper) | 把元素收集到Map集合中 |
例如将List 转为 Map
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
Collections.addAll(list,
new Student(1, "张三"),
new Student(2, "李四"),
new Student(1, "王五"));
Map<Integer, String> map =
list.stream().collect(
Collectors.toMap(Student::getId, Student::getName, (v1, v2) -> v1));
System.out.println(map);
}
结果如下:
{1=张三, 2=李四}
toMap时只用到两个参数,第一个设定Key,第二个设定value。但如果Key重复的话,那就需要用到第三个参数,可以这么写(v1, v2)-> v1, 当key重复时使用之前的,如果是(v1,v2) -> v2,则表示覆盖