JAVA8 - 流 & 方法引用
流的使用
Stream 操作的三个步骤:
- 创建Stream
一个数据源(如:集合、数组),获取一个流 - 中间操作
一个中间操作链,对数据源的数据进行处理 - 终止操作(终端操作)
一个终端操作,执行中间操作链,并产生结果
创建 Stream 对象
package com.day01;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
package com.study.map.immutable;
import java.util.*;
import java.util.stream.Stream;
public class Demo2 {
public static void main(String[] args) {
//单列集合获取流
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3");
list.stream().forEach(s -> System.out.println(s));
//双列集合
HashMap<String, Integer> map = new HashMap<>();
map.put("aaa", 111);
map.put("bbb", 222);
map.put("ccc", 333);
map.put("ddd", 444);
map.keySet().stream().forEach(s -> System.out.println(s)); //输出map的每个键
/*
aaa
ccc
bbb
ddd
*/
map.entrySet().stream().forEach(s -> System.out.println(s));
/*
aaa=111
ccc=333
bbb=222
ddd=444
*/
//数组
int[] arrr = {1,2,3,4,5};
Arrays.stream(arrr).forEach(s -> System.out.println(s));
/*
1
2
3
4
5
*/
//通过Stream 类中的静态方法of()
Stream<String> stream3 = Stream.of("a", "b", "c");
stream3.forEach(s -> System.out.println(s));
}
}
中间方法
注意细节:
- 中间方法,返回的Steam流,一旦操作过终结操作,就不能再次使用,建议使用链式编程
- 修改Stream流中的数据,不会影响原来集合或数组中的数据
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
public class StreamDemo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张蹒跚");
Stream<String> sream1 = list.stream().filter(s -> s.startsWith("张"));
sream1.forEach(s-> System.out.println(s)); //forEach 之后该流不能再使用
// Stream<String> stream2 = sream1.filter(s -> s.length() == 3); sream1 再次使用 会抛Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or close
//map 使用方法:类型转换
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2,"李四-25","小明-32");
list2.stream().map(s->Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.print(s)); //253212345678
//合并流
ArrayList<Integer> list3 = new ArrayList<>();
Collections.addAll(list3,1,2,3,4);
ArrayList<Integer> list4 = new ArrayList<>();
Collections.addAll(list4,5,6,7,8);
Stream.concat(list3.stream(),list4.stream()).forEach(s-> System.out.print(s)); //12345678
System.out.println("--------------------------------------------------");
//distanct 去重, 依赖equals 和 hashcode 方法
ArrayList<String> list5 = new ArrayList<>();
Collections.addAll(list5,"5","5","6","6");
list5.stream().distinct().forEach(s-> System.out.print(s)); //56
}
}
Stream 流的终结方法
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class StreamDemo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张蹒跚");
//count();
System.out.println(list.stream().count()); //5
//toArray() - 匿名内部类写法
/* String[] strings = list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) { //value 代表list的长度
return new String[value];
}
});
System.out.println(Arrays.toString(strings));*/ //[张无忌, 周芷若, 赵敏, 张强, 张蹒跚]
//toArray() - lambda 写法
String[] strings = list.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(strings)); //[张无忌, 周芷若, 赵敏, 张强, 张蹒跚]
}
}
collect() 收集方法
package com.study.streamdemo;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public class StreanDemo3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-18", "周芷若-女-20", "赵敏-女-20", "张强-男-21", "张蹒跚-男-21");
//过滤数据后转换为ArrayList
List<String> list2 = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());
System.out.println(list2); //[张无忌-男-18, 张强-男-21, 张蹒跚-男-21]
//过滤数据后转换为Hashset
Set<String> set = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toSet());
System.out.println(set); //[张蹒跚-男-21, 张强-男-21, 张无忌-男-18]
//转换为HashMap - 匿名内部类写法
/*
toMap参数介绍:
- 第一个参数函数式接口Function<String, String>:
* 第一个String是流中的数据类型
* 第二个String是转换后map的健的类型
- 第二个参数函数式接口Function<String, String>:
* 第一个String是流中的数据类型
* 第二个String是转换后map的值的类型
*/
Map<String, Integer> map = list.stream().collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
},
new Function<String, Integer>() { //
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}
}));
System.out.println(map); //{张强=21, 周芷若=20, 赵敏=20, 张无忌=18, 张蹒跚=21}
//转换为HashMap - lambda写法
Map<String, String> map2 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(
s -> s.split("-")[0],
s -> s.split("-")[2]));
System.out.println(map2); //{张强=21, 张无忌=18, 张蹒跚=21}
}
}
Stream 总结
方法引用
什么是方法引用?
把已经存在的方法拿过来用,当作函数式接口中抽象方法的方法体
::
是什么符号?
方法引用符
方法引用时要注意什么?
- 需要有函数式接口
- 被引用方法必须已经存在
- 被引用方法的形参和返回值需要跟抽象方法保持一致
- 被引用方法的功能要满足当前需求
静态方法引用
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class StreamDemo4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1","2","3","4");
//需求:将list中的数据转化为int
list.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
});
//list.stream().map(s -> Integer.parseInt(s)).forEach(s-> System.out.println(s));
//lambda 写法
list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));
}
}
成员方法引用
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class StreamDemo5 {
/*
引用成员方法:
前提:引用的方法签名和函数式接口的签名一致
1.其他类:其他类对象::方法
2.本类: this::方法
3.其他类: super::方法发
*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张蹒跚");
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("张") && s.length() == 3;
}
}).forEach(s -> System.out.println(s)); //张无忌,张蹒跚
// StringJudge 类的 stringJudge 签名要与filter函数参数的函数式接口签名一致
list.stream().filter(new StringJudge()::stringJudge).forEach(s-> System.out.println(s)); //张无忌,张蹒跚
}
}
class StringJudge{
public boolean stringJudge(String s){
return s.startsWith("张") && s.length() == 3;
}
}
构造方法引用
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class StreamDemo6 {
public static void main(String[] args) {
//需求:将list中的字符串转换为Student对象
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌,16","周芷若,27","赵敏,24","张强,13","张蹒跚,21");
//匿名内部类写法
List<Student> list2 = list.stream().map(new Function<String, Student>() {
@Override
public Student apply(String s) {
String[] split = s.split(",");
return new Student(split[0],Integer.parseInt(split[1]));
}
}).collect(Collectors.toList());
System.out.println(list2);
//方法引用构造方法
List<Student> collect = list.stream().map(Student::new).collect(Collectors.toList());
System.out.println(collect);
//[Student{name = 张无忌, age = 16}, Student{name = 周芷若, age = 27}, Student{name = 赵敏, age = 24}, Student{name = 张强, age = 13}, Student{name = 张蹒跚, age = 21}]
}
}
类名引用成员方法
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
public class StreamDemo7 {
/*
引用格式:Class::实例方法
该格式引用的规则:
1.需要有函数式接口
2.被引用的方法已经存在
3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
4.被引用方法的功能需要满足当前需求
抽象方法形参详解:
1.第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
在Stream流中,第一个参数一般都表示流里卖弄的每一个元素
假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
2.第二个参数到最后一个参数,跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用法的方法是无参的成员方法
*/
public static void main(String[] args) {
//需求:将list中的字符串转换小写
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "aaa","bbb","ccc","ddd","eee");
list.stream().map(String::toUpperCase).forEach(s-> System.out.print(s)); //AAABBBCCCDDDEEE
}
}
数组构造方法引用
package com.study.streamdemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class StreamDemo8 {
/*
引用数组的构造方法
*/
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
Integer[] integers = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(integers)); //[1, 2, 3, 4, 5]
}
}
方法引用总结
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/16704869.html