title: stream与函数式接口
date: 2019-07-24 14:03:02
categories:
- java基础
tags:
1. 思维导图
2. Stream 与函数式接口
2.1. 获取流
- 所有的 Collection 集合都可以通过 stream 默认方法获取流
- Stream 接口的静态方法 of 可以获取数组对应的流
- Map 不是集合类型,需要根据 key, value, entry 分别获取相应的流
2.2. 流的方法
2.2.1. forEach
- void forEach(Consumer<? super T> action);
2.2.2. filter
- Stream filter(Predicate<? super T> predicate);
2.2.3. map
将流中的元素映射到另一个流中,通常是用来转换成另一个类型
- Stream map(Function<? super T, ? extends R> mapper);
2.2.4. count
- long count();
2.2.5. limit
- Stream limit(long maxSize);
2.2.6. skip
- Stream skip(long n);
2.2.7. concat
- static Stream concat(Stream<? extends T> a, Stream<? extends T> b)
2.3. collect 的使用
2.3.1. 转换为 list
- collect.()
2.3.2. 转换为 map
传入 key, value 即可
- public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper) - 例如:Stream.concat(one.stream(), two.stream()).collect(Collectors.toMap(s -> s, s -> new Person(s)));
2.4. 流的方法练习
package javaBase.Stream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author jhmarryme.cn
* @date 2019/7/24 11:21
*/
public class StreamAndFunctionalInterface {
/**
* 测试流的各种方法结合常用函数式接口的使用
* @param args
*/
public static void main(String[] args) {
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
// 1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
one.stream().filter(s -> s.length() == 3).collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("------------");
// 2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
one.stream().limit(3).collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("------------");
// 3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
two.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("------------");
// 4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
two.stream().skip(2).collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("------------");
// 5. 将两个队伍合并为一个队伍;存储到一个新集合中。
Stream<String> stream = Stream.concat(one.stream(), two.stream());
// stream.collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("------------");
// 6. 根据姓名创建`Person`对象;存储到一个新集合中。
// 7. 打印整个队伍的Person对象信息。
stream.map(s -> {
return new Person(s);
}).collect(Collectors.toList()).forEach(person -> System.out.println(person.toString()));
//8. 补充, 将list映射为map
final Map<String, Person> map = Stream.concat(one.stream(), two.stream()).collect(Collectors.toMap(s -> s, s -> new Person(s)));
final Set<Map.Entry<String, Person>> entries = map.entrySet();
for (Map.Entry<String, Person> entry : entries) {
System.out.print(entry.getKey());
System.out.println(" : " + entry.getValue().toString());
}
//将int数组转换为list
int[] arr = {1,2,3,2,2,2,5,4,2};
//boxed装箱
final List<Integer> collect = Arrays.stream(arr).boxed().collect(Collectors.toList());
final Iterator<Integer> iterator = collect.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next() + " ");
}
//将list转换为int[], 因为int不是包装类型, 需要做转换
final int[] array = collect.stream().mapToInt(Integer::intValue).toArray();
for (int i : array) {
System.out.print(i + " ");
}
}
}
2.5. 函数式接口
有且仅有一个抽象方法的接口
2.5.1. Supplier
生产一个数据
- T get()
2.5.2. Consumer
是消费一个数据
- void accept(T t)
- 默认方法:andThen
2.5.3. Predicate
对某种类型的数据进行判断
- boolean test(T t)
- 默认方法:and or negate
2.5.4. Function<T,R>
根据一个类型的数据得到另一个类型的数据
- R apply(T t)
- 默认方法:andThen
2.6. 函数式接口方法练习
2.6.1. 比较器
package javaBase.functionalInterface.functionalInterfaceDemo;
import java.util.Arrays;
/**
* 通过lambda表达式 作为比较器
* @author jhmarryme.cn
* @date 2019/7/22 9:43
*/
public class LambdaForComparatorDemo {
public static void main(String[] args) {
String[] array = { "abc", "ab", "abcd" };
System.out.println(Arrays.toString(array));
Arrays.sort(array, (a, b) -> {
return a.length() - b.length();
});
System.out.println(Arrays.toString(array));
}
}
2.6.2. consumer
package javaBase.functionalInterface.functionalInterfaceDemo;
import java.util.function.Consumer;
/**
* 测试Consumer接口
* 消费一个指定泛型的数据, 无返回值
* 可通过andThen组合操作
* @author jhmarryme.cn
* @date 2019/7/22 11:21
*/
public class LambdaForConsumerDemo {
public static void consumerString(String[] info, Consumer<String> con1, Consumer<String> con2, Consumer<String> con3){
for (String s : info) {
con1.andThen(con2).andThen(con3).accept(s);
}
}
public static void main(String[] args) {
String[] array = { "迪丽热巴,女, 14", "古力娜扎,女, 12", "马尔扎哈,男, 121" };
consumerString(array,
s -> System.out.print("姓名: " + s.split(",")[0]),
s -> System.out.print("性别: " + s.split(",")[1]),
s -> System.out.println("年龄: " + s.split(",")[2])
);
}
}
2.6.3. supplier
package javaBase.functionalInterface.functionalInterfaceDemo;
import java.util.function.Supplier;
/**
* 测试Supplier接口
* 包含一个无参的方法, 用来获取一个泛型参数指定类型的对象数据
* @author jhmarryme.cn
* @date 2019/7/22 9:52
*/
public class LambdaForSupplierDemo {
public static void main(String[] args) {
/*String msgA = "Hello";
String msgB = "World";
System.out.println(getString(() -> msgA + msgB));*/
int arr[] = {2,3,4,52,333,23};
System.out.println(getMax(() -> {
int max = arr[0];
for (int i : arr) {
max = i > max ? i : max;
}
return max;
}));
}
public static int getMax(Supplier<Integer> integerSupplier){
return integerSupplier.get();
}
public static String getString(Supplier<String> stringSupplier){
return stringSupplier.get();
}
}
2.6.4. function
package javaBase.functionalInterface.functionalInterfaceDemo;
import java.util.function.Function;
/**
* 通过函数式结构练习function接口
* 根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件
* @author jhmarryme.cn
* @date 2019/7/22 13:15
*/
public class LambdaForFunctionDemo {
/**
* 根据接口的泛型
* apply方法中参数类型为String, 返回Integer
* @param integerFunction
*/
public static void method(Function<String, Integer> integerFunction){
final Integer apply = integerFunction.apply("5");
System.out.println(apply + 20);
}
/**
* 在前一个function的基础上再进行处理
* 第二个function的第一个泛型必须为前一个function的后一个泛型
* 相当于前一个的结果为Integer, 后一个就必须用Integer接收
* @param f1
* @param f2
*/
public static void methood(Function<String, Integer> f1, Function<Integer, Integer> f2){
final Integer apply = f1.andThen(f2).apply("1");
System.out.println(apply);
}
/**
* 截取数字部分, 得到的结果加上100返回
* @param str
* @param f1
* @param f2
* @return
*/
public static Integer getAgeNum(String str, Function<String, Integer> f1, Function<Integer, Integer> f2){
return f1.andThen(f2).apply(str);
}
public static void main(String[] args) {
// method((s) -> Integer.parseInt(s));
// methood(s -> Integer.parseInt(s)+1, i -> i = ((int)Math.pow(i, 10)));
String str = "赵丽颖,20";
final Integer ageNum = getAgeNum(str,
s -> Integer.parseInt(s.split(",")[1]),
i -> i = i + 100
);
System.out.println(ageNum);
}
}
2.6.5. predicate
package javaBase.functionalInterface.functionalInterfaceDemo;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* 通过函数式接口练习predicate相关的方法
* 对泛型指定数据类型进行判断, 得到一个布尔值.
* 包含与或非and, or, negate
* @author jhmarryme.cn
* @date 2019/7/22 12:54
*/
public class LambdaForPredicateDemo {
public static Boolean method( Predicate<String> stringPredicate){
return stringPredicate.test("helloWorld");
}
public static void method(Predicate<String> p1, Predicate<String> p2){
final boolean helloWorld = p1.or(p2).test("HelloWorld");
System.out.println(helloWorld);
}
public static ArrayList<String> filterString(String[] arr, Predicate<String> stringPredicate){
final ArrayList<String> list = new ArrayList<>();
for (String s : arr) {
if (stringPredicate.test(s)) {
list.add(s);
}
}
return list;
}
public static void main(String[] args) {
/*System.out.println(method(s -> {
return s.length() > 5;
}));
*/
// method(s -> s.contains("el"), s -> s.length() > 10);
/**
* 筛选条件:
* 必须为女生;
* 姓名为4个字。
*/
String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女" };
final ArrayList<String> arrayList = filterString(array, s -> {
return s.split(",")[1].equals("女") && s.split(",")[0].length() == 4;
});
for (String s : arrayList) {
System.out.println(s);
}
}
}
2.6.6. lambda延迟加载
package javaBase.functionalInterface.DelayForLambda;
import static javaBase.functionalInterface.DelayForLambda.MessageBuilder.MAX_NUM;
/**
* 测试lambda表达式的延迟执行
* 优化性能, 在不符合条件时, 不会执行lambda的内容
* @author jhmarryme.cn
* @date 2019/7/22 9:32
*/
public class DelayForLambdaDemo {
public static void log(int level, MessageBuilder builder){
if (level == 1) {
System.out.println(builder.messageBuilder());
}
}
public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
//这里的拼接字符串 在条件不成立时不会执行
log(1, () -> msgA + msgB + msgC );
}
}
package javaBase.functionalInterface.DelayForLambda;
/**
* @author jhmarryme.cn
* @date 2019/7/22 9:33
*/
@FunctionalInterface
public interface MessageBuilder {
int MAX_NUM = 97;
/**
* 测试lambda延迟加载
* @return
*/
String messageBuilder();
}