0
点赞
收藏
分享

微信扫一扫

java中lambda表达式的使用案例技巧


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)

  1. Object::instanceMethod
  2. Class::staticMethod
  3. 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

  1. map遍历

itemsMap.forEach((k,v)->System.out.println("Item : " + k + " Count : " + v));

List

注意排序中的元素不能存在null值

  1. 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());

  1. list遍历

words.forEach(System.out::println);

  1. list转map(key去重)

Map<String, Word> wordMapMap = wordList.stream().collect(Collectors.toMap(Word::getName, k -> k, (k1, k2) -> k1));

  1. list转map(key不能重复)

Map<Integer,Word> userMap = wordList.stream().collect(Collectors.toMap(Word::getCountry, k -> k));

  1. list分组

Map<String, List<Word>> groupMap = wordList.stream().collect(Collectors.groupingBy(Word::getName));

  1. list多重分组

// 先按名称分组,再在名称分组的基础上按国家分组
Map<String, Map<Integer, List<Word>>> map2 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.groupingBy(Word::getCountry)));

  1. 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());

  1. list统计求和

int sum = wordList.stream().mapToInt(Word::getCountry).sum();
double sum = words.stream().mapToDouble(Word::getCountry).sum();

  1. list分组统计个数

按名称分组统计个数
Map<String, Long> collectCnt = wordList.stream().collect(Collectors.groupingBy(Word::getName, Collectors.counting()));

  1. list统计分析

// 
Map<String, LongSummaryStatistics> map3 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.summarizingLong(Word::getCountry)));

  1. list多重分组统计分析

Map<String, Map<Integer, LongSummaryStatistics>> map3 = words.stream().collect(Collectors.groupingBy(Word::getName,Collectors.groupingBy(Word::getCountry,Collectors.summarizingLong(Word::getCountry))));

  1. list去重(需根据实际情况重写Word的equals与hashCode)

List<Word> list1= list.stream().distinct().collect(Collectors.toList());

  1. list元素字符串拼装

String result = words.stream().map(Word::getName).collect(Collectors.joining("," , "[" , "]"));

  1. 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());

  1. list求交集

List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());

  1. list求差集

List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList());

数组

  1. 数组排序

// 原始版
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()));

  1. 数组统计某元素个数

long num = Arrays.stream(name).filter(x -> x.equals("tiger")).count();

  1. 数组去重过滤并转化成集合

List<String> filterList = Arrays.stream(name).filter(x -> !x.equals("赵强")).collect(Collectors.toList());

  1. 数组过滤,并对元素加后缀并转集合

List<String> filterList = Arrays.stream(name).filter(x -> !x.equals("tiger")).map(y -> y.concat(".jpg")).collect(Collectors.toList());

  1. 数组统计求和

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对象,如从一个数据源来执行一个查询;
  • 操作流:一个包含了各种操作的操作链;
  • 结束流:一个终端操作,形成一个结果集或值
  1. 筛选/切片:使用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);

  1. 映射:对流中的每个元素应用映射函数,变换成新的对象

// 创建流
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);

  1. 查找/匹配: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);

  1. 归约:使用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);

举报

相关推荐

0 条评论