Functional Interface
一个接口仅有一个抽象方法,比如Runnable、Comparator等。在任何一个需要Functional Interface对象的地方,都可以使用lambda表达式。
Method Reference
将lambda表达式的参数作为参数传递给一个方法,他们的执行效果是相同的,则该lambda表达式 可以使用Method Reference表达,以下两种方式是等价的:
System.out::println
(x) -> System.out.println(x)
Math::pow
(x, y) -> Math.pow(x, y)
Object::instanceMethod
Class::staticMethod
Class::instanceMethod
对于前两种方式,对应的lambda表达式的参数和method的参数是一致的
对于第三种方式,对应的lambda表达式的语句体中,第一个参数作为对象,调用method,将其它参数
String::compareToIgnoreCase
(s1, s2) -> s1.compareToIgnoreCase(s2)
Constructor Reference与Method Reference类似,只不过是特殊的method:new,具体调用的是哪个构造函数,由上下文环境决定,比如:
List<String> labels = ...;
Stream<Button> stream = labels.stream().map(Button::new);
Button::new等价于(x) -> Button(x),所以调用的构造函数是:Button(x); 除了创建单个对象,也可以创建对象数组,如下面两种方式等价:
int[]::new
(x) -> new int[x]
Map
-
map遍历
itemsMap.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));
-
…
List
注意排序中的元素不能存在null值
-
List排序
// 原始版 words.sort((Word first, Word second) -> first.getName().compareTo(second.getName())); // 精简版 Collections.sort(words, Comparator.comparing(Word::getName)); // 精简版,推荐使用这种 words.sort(Comparator.comparing(Word::getName)); // 多重排序(连个都升序) words.sort(Comparator.comparing(Word::getName).thenComparingInt(Word::getCountry)); // 多重排序(第一个升,第二个降) words.sort(Comparator.comparing(Word::getName).reversed().thenComparingInt(Word::getCountry).reversed()); // 排序默认是升序,降序其实就是多调用一下reversed()方法 words.sort(Comparator.comparing(Word::getName).reversed());
-
list遍历
words.forEach(System.out::println);
-
list转map(key去重)
Map<String, Word> wordMapMap = wordList.stream().collect(Collectors.toMap(Word::getName, k -> k, (k1, k2) -> k1));
-
list转map(key不能重复)
Map<Integer,Word> userMap = wordList.stream().collect(Collectors.toMap(Word::getCountry, k -> k));
-
list分组
Map<String, List<Word>> groupMap = wordList.stream().collect(Collectors.groupingBy(Word::getName));
-
list多重分组
// 先按名称分组,再在名称分组的基础上按国家分组 Map<String, Map<Integer, List<Word>>> map2 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.groupingBy(Word::getCountry)));
-
list匹配过滤
// 过滤出名称等于tiger的元素 List<Word> filterList = wordList.stream().filter(v -> v.getName().equals("tiger")).collect(Collectors.toList()); // 打印出名称包含老子的元素 wordList.stream().filter(v -> v.getName().contains("老")).forEach(System.out::println); // 过滤出国家编码大于2的元素 List<Word> filterList = wordList.stream().filter(v -> v.getCountry() > 2).collect(Collectors.toList()); // 过滤出国家编码等于1且名称包含tiger的元素 Predicate<Word> equals1 = v -> v.getCountry().equals(1); Predicate<Word> contains1 = v -> v.getName().contains("tiger"); List<Word> filterList = wordList.stream().filter(contains1.and(equals1)).collect(Collectors.toList()); // 过滤出值大于25的元素 List<Double> filteredCost = cost.stream().filter(x -> x > 25.0).collect(Collectors.toList());
-
list统计求和
int sum = wordList.stream().mapToInt(Word::getCountry).sum(); double sum = words.stream().mapToDouble(Word::getCountry).sum();
-
list分组统计个数
按名称分组统计个数 Map<String, Long> collectCnt = wordList.stream().collect(Collectors.groupingBy(Word::getName, Collectors.counting()));
-
list统计分析
// Map<String, LongSummaryStatistics> map3 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.summarizingLong(Word::getCountry)));
-
list多重分组统计分析
Map<String, Map<Integer, LongSummaryStatistics>> map3 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.groupingBy(Word::getCountry,Collectors.summarizingLong(Word::getCountry))));
-
list去重(需根据实际情况重写Word的equals与hashCode)
List<Word> list1= list.stream().distinct().collect(Collectors.toList());
-
list元素字符串拼装
String result = words.stream().map(Word::getName).collect(Collectors.joining("," , "[" , "]"));
-
list对象集合转属性集合
List<String> result = words.stream().map(Word::getName).collect(Collectors.toList()); // 转属性集合时顺便做下处理 List<String> result = words.stream().map(y -> y.getName().concat(".jpg")).collect(Collectors.toList());
-
list求交集
List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
-
list求差集
List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList());
-
…
数组
-
数组排序
// 原始版 Arrays.sort(people, (first, second) -> Integer.compare(first.length(), second.length())); // 精简版 Arrays.sort(people, Comparator.comparingInt(String::hashCode)); // 数组降序 Arrays.sort(people, (second, first) -> Integer.compare(first.length(), second.length()));
-
数组统计某元素个数
long num = Arrays.stream(name).filter(x -> x.equals("tiger")).count();
-
数组去重过滤并转化成集合
List<String> filterList = Arrays.stream(name).filter(x -> !x.equals("赵强")).collect(Collectors.toList());
-
数组过滤,并对元素加后缀并转集合
List<String> filterList = Arrays.stream(name).filter(x -> !x.equals("tiger")).map(y -> y.concat(".jpg")).collect(Collectors.toList());
-
数组统计求和
int num = Arrays.stream(arr).reduce(0, Integer::sum); double sum = Arrays.asList(10.0, 20.0, 30.0).stream().map(x -> x + x * 0.05).reduce(Double::sum).get(); double sum = Stream.of(10.0, 20.0, 30.0).map(x -> x + x * 0.05).reduce(Double::sum).get(); int sum = Stream.of(1, 2, 3, 4, 5).map(x -> x + x * 5).reduce(Integer::sum).get();
-
…
求和
BinaryOperator<Integer> add = Integer::sum;
Integer x = add.apply(20, 30);
线程
private static void lambdaRunnable() {
int age = 20;
Runnable r2 = () -> {
System.out.println(age);
System.out.println("Hello world two!"+age);
};
r2.run();
}
流的筛选/切片/查找/匹配/映射/归约操作
1.先来两个概念:
-
流(Stream):一个元素序列。位于包java.util.stream.Stream,注意这个序列是可以串行或并行处理的。有多种方式建立流,最常见的是从集合(Collection)对象获取,有序集合如List的流有序,Set的流则无序。
-
Lambda表达式:流式处理的绝佳搭档!什么是Lambda表达式?略。哪里可以用Lambda表达式?需要实现一个函数式接口(只定义了一个抽象函数的接口)的地方就可以使用Lambda表达式,代替匿名类方式。
2.流式处理特点:
-
流水线:流操作可返回一个流,多个操作从而可形成一个链,
-
内部迭代:使用Iterator/forEach显式迭代器为外部迭代,流的迭代是流内部完成的,只需声明,是内部迭代,
-
一次使用:每个流只能消费一次,不能结束后又从头开始!
3.流的一般使用:
-
建立流:创建一个Stream对象,如从一个数据源来执行一个查询;
-
操作流:一个包含了各种操作的操作链;
-
结束流:一个终端操作,形成一个结果集或值
-
筛选/切片:使用filter/skip/limit/distinct方法过滤
// 创建流 Stream<Fruit> fruitStream = fruitList.stream(); // 过滤 Stream<Fruit> filteredStream = fruitStream.filter(d -> "中国".equals(d.getOrigin())); // 去掉重复元素 Stream<Fruit> distinctStream = filteredStream.distinct(); // 打印流中元素,forEach是终端操作,如果这里使用了,则collect方法无法使用,即一个流只能消费一次 // distinctStream.forEach(System.out::println); // 跳过1个元素, Stream<Fruit> skippedStream = distinctStream.skip(1); // 切片,参数为maxSize Stream<Fruit> limitStream = skippedStream.limit(4); // 结束,collect方法是收集器,如果这里使用了,则forEach无法使用,即一个流只能有一个终端操作 List<Fruit> newList = limitStream.collect(Collectors.toList()); // 打印结果,lambda方式 newList.forEach(System.out::println); // 链式操作,和上面效果一样,一气呵成,真爽! List<Fruit> newList2 = fruitList.stream() .filter(d -> "中国".equals(d.getOrigin())) .distinct() .skip(1) .limit(4) .collect(Collectors.toList()); // 打印结果集 newList2.forEach(System.out::println);
-
映射:对流中的每个元素应用映射函数,变换成新的对象
// 创建流 Stream<Fruit> fruitStream = fruitList.stream(); //转换,变为String流 Stream<String> stringStream = fruitStream.map(Fruit::getName); //过滤,名称以A开头 Stream<String> filteredStream = stringStream.filter(str -> "A".equals(String.valueOf(str.charAt(0)))); //终端操作,set自动去重复 Set<String> stringSet = filteredStream.collect(Collectors.toSet()); //打印结果集 stringSet.forEach(System.out::println); //链式语法实现,请君想象下JDK7的实现, fruitList.stream() .map(Fruit::getName) .filter(str -> "A".equals(str.substring(0,1))) .collect(Collectors.toSet()) .forEach(System.out::println);
-
查找/匹配:StreamAPI通过allMatch,anyMatch,noneMatch,findFirst,findAny方法找到符合的元素
// 注意这里每个都要重建一个流 // 是否全部价格大于50 boolean almach = fruitList.stream().allMatch(fruit -> fruit.getPrice() > 50); // 是否至少有一种产自America boolean anyMatch = fruitList.stream().anyMatch(fruit -> "America".equals(fruit.getOrigin())); // 找出流中第3个, Optional<Fruit> thirdOne = fruitList.stream().skip(2).findFirst(); // 存在则打印,防止NPE thirdOne.ifPresent(System.out::println); // 找出流中任意一个,, Optional<Fruit> anyOne = fruitList.stream().findAny(); // ifPresent,值存在则执行操作,否则 do nothing! anyOne.ifPresent(System.out::println);
-
归约:使用reduce对流中元素累积计算,最后得到一个值
// 注意这里每个都要重建一个流 // reduce求和 int totalPrice = fruitList.stream() .filter(fruit -> "Japan".equals(fruit.getOrigin())) // 映射转换为Integer流 .map(Fruit::getPrice) // reduce归约计算 // 也可使用reduce(0,(a,b) -> a+b); .reduce(0,Integer::sum); totalPrice.ifPresent(System.out::println); // reduce计算最大 Optional<Integer> maxPrice = fruitList.stream() .map(Fruit::getPrice) // 归约计算最大值: // 这里也可以使用reduce((x,y) -> x>y?x:y) .reduce(Integer::max); // ifPresent,值存在则执行操作,否则 do nothing! maxPrice.ifPresent(System.out::println); // reduce计算最小值 Optional<Integer> minPrice = fruitList.stream() .map(Fruit::getPrice) // 归约计算最小值:也可以使用reduce((x,y) -> x<y?x:y) .reduce(Integer::min); // ifPresent,值存在则执行操作,否则 do nothing! minPrice.ifPresent(System.out::println);
-
…