在对Java8 发布的Lambda表达式进行一定了解之后,发现Lambda最核心的就是 结合Stream API对集合数据的遍历、提取、过滤、排序等一系列操作的简化,以一种函数式编程的方式,对集合进行操作。下面总结了几种常用的示例Demo;
Lambda表达式的语法
基本语法:
(parameters) -> expression 或 (parameters) ->{ statements; }
含义
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| () -> 5
x -> 2 * x
(x, y) -> x – y
(int x, int y) -> x + y
(String s) -> System.out.print(s)
|
用lambda表达式实现Runnable
lambda表达式替换了原来匿名内部类的写法,没有了匿名内部类繁杂的代码实现,而是突出了,真正的处理代码。最好的示例就是 实现Runnable 的线程实现方式了: 用() -> {}
代码块替代了整个匿名类
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void test(){ new Thread((new Runnable() { @Override public void run() { System.out.println("匿名内部类 实现线程"); } })).start(); new Thread( () -> System.out.println("java8 lambda实现线程")).start(); }
|
forEach 遍历集合
使用 forEach方法,直接通过一行代码即可完成对集合的遍历:
1 2 3 4 5
| @Test public void test1(){ List<Person> list = getPersonList(); list.forEach(person -> System.out.println(person.toString())); }
|
执行结果:
1 2 3 4
| Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) Person(name=li, age=18, sex=female) Person(name=wang, age=21, sex=female)
|
双冒号::
表示方法引用,可以引用其他方法
1 2 3 4 5 6 7
| @Test public void test2(){ List<Person> list = getPersonList(); Consumer<Person> changeAge = e -> e.setAge(e.getAge() + 3); list.forEach(changeAge); list.forEach(System.out::println); }
|
执行结果:
1 2 3 4
| Person(name=liu, age=25, sex=male) Person(name=zhao, age=24, sex=male) Person(name=li, age=21, sex=female) Person(name=wang, age=24, sex=female)
|
filter 对集合进行过滤
filter 可以根据传入的 Predicate 对象,对集合进行过滤操作,Predicate 实质就是描述了过滤的条件:
1 2 3 4 5 6
| @Test public void test3(){ List<Person> list = getPersonList(); list.stream().filter(e -> e.getAge() > 20) .forEach(e -> System.out.println(e.toString())); }
|
执行结果:
1 2 3
| Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) Person(name=wang, age=21, sex=female)
|
当需要通过 多个过滤条件对集合进行过滤时,可以采取两种方式:
可以通过调用多次filter
通过传入不同的 Predicate
对象来进行过滤
也可以通过 Predicate
对象的 and
or
方法,对多个Predicate
对象进行 且 或 操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Test public void test4(){ List<Person> list = getPersonList();
Predicate<Person> ageFilter = e -> e.getAge() > 20; Predicate<Person> sexFilter = e -> e.getSex().equals("male");
list.stream().filter(ageFilter) .filter(sexFilter) .forEach(e -> System.out.println(e.toString())); System.out.println("----------------------------"); list.stream().filter(ageFilter.and(sexFilter)) .forEach(e -> System.out.println(e.toString())); }
|
执行结果:
1 2 3 4 5
| Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) ---------------------------- Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male)
|
limit 限制结果集的数据量
limit 可以控制 结果集返回的数据条数:返回三条数据,返回年龄>20的前两条数据
1 2 3 4 5 6 7 8 9
| @Test public void test5(){ List<Person> list = getPersonList(); list.stream().limit(3).forEach(e -> System.out.println(e.toString()));
System.out.println("----------------------------"); list.stream().limit(2).filter(e -> e.getAge() > 20) .forEach(e -> System.out.println(e.toString())); }
|
执行结果:
1 2 3 4 5 6
| Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) Person(name=li, age=18, sex=female) ---------------------------- Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male)
|
sorted 排序
通过sorted,可以按自定义的规则,对数据进行排序,可以用两种写法,分别按 年龄 和 姓名排序
1 2 3 4 5 6 7 8 9 10 11
| @Test public void test6(){ List<Person> list = getPersonList(); list.stream().sorted((p1,p2) -> (p1.getAge() - p2.getAge())) .forEach(e -> System.out.println(e.toString())); System.out.println("----------------------------"); list.stream().sorted(Comparator.comparing(Person::getName)) .forEach(e -> System.out.println(e.toString())); }
|
执行结果:
1 2 3 4 5 6 7 8 9
| Person(name=li, age=18, sex=female) Person(name=zhao, age=21, sex=male) Person(name=wang, age=21, sex=female) Person(name=liu, age=22, sex=male) ---------------------------- Person(name=li, age=18, sex=female) Person(name=liu, age=22, sex=male) Person(name=wang, age=21, sex=female) Person(name=zhao, age=21, sex=male)
|
max min 获取结果中 某个值最大最小的的对象
max min 可以按指定的条件,获取到最大、最小的对象,当集合里有多个满足条件的最大最小值时,只会返回一个对象。
如: 返回年龄最大的人
1 2 3 4 5 6 7
| @Test public void test7(){ List<Person> list = getPersonList(); Person oldest = list.stream().max(Comparator.comparing(Person::getAge)).get(); System.out.println(oldest.toString()); }
|
执行结果:
1
| Person(name=liu, age=22, sex=male)
|
map 与 reduce也是两个十分重要的方法
map
:对集合中的每个元素进行遍历,并且可以对其进行操作,转化为其他对象,如将集合中的每个人的年龄增加3岁
1 2 3 4 5 6 7 8 9 10
| @Test public void test8(){ List<Person> list = getPersonList(); System.out.println("修改前:"); list.forEach(e -> System.out.println(e.toString())); System.out.println("修改后:"); list.stream().map(e -> e.setAge(e.getAge() + 3 )) .forEach(e -> System.out.println(e.toString())); }
|
执行结果:
1 2 3 4 5 6 7 8 9 10
| 修改前: Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) Person(name=li, age=18, sex=female) Person(name=wang, age=21, sex=female) 修改后: Person(name=liu, age=25, sex=male) Person(name=zhao, age=24, sex=male) Person(name=li, age=21, sex=female) Person(name=wang, age=24, sex=female)
|
reduce
:也是对所有值进行操作,但它是将所有值,按照传入的处理逻辑,将结果处理合并为一个
如:将集合中的所有整数相加,并返回其总和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test public void test9(){
List<Integer> ages = Arrays.asList(2,5,3,4,7); int totalAge = ages.stream().reduce((sum,age) -> sum + age).get();
System.out.println(totalAge); int totalAge1 = ages.stream().reduce(0,(sum,age) -> sum+age); List<Integer> initList = Lists.newArrayList(); int initTotalAge = initList.stream().reduce(0,(sum,age) -> sum+age);
System.out.println("totalAge1: "+ totalAge1 + " initTotalAge: " + initTotalAge); }
|
执行结果:
1 2
| 21 totalAge1: 21 initTotalAge: 0
|
collect方法以集合中的元素为基础,生成新的对象
在实际中,我们经常会以集合中的元素为基础,取其中的数据,来生成新的结果集,例如 按照过滤条件,返回新的List,
或者将集合转化为 Set
或Map
等操作,通过collect
方法实现是十分简便的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Test public void test10(){ List<Person> list = getPersonList(); List<Person> filterList = list.stream().filter(e -> e.getAge() >20).collect(Collectors.toList()); filterList.forEach(e -> System.out.println(e.toString()));
String nameStr = list.stream().map(Person::getName).collect(Collectors.joining(",")); System.out.println(nameStr); Set<String> nameSet = list.stream().map(person -> person.getName()).collect(Collectors.toSet()); nameSet.forEach(e -> System.out.print(e + ","));
System.out.println(); System.out.println("map--------"); Map<String,Person> personMap = list.stream().collect(Collectors.toMap(Person::getName,person -> person)); personMap.forEach((key,val) -> System.out.println(key + ":" + val.toString())); }
|
执行结果:
1 2 3 4 5 6 7 8 9 10
| Person(name=liu, age=22, sex=male) Person(name=zhao, age=21, sex=male) Person(name=wang, age=21, sex=female) liu,zhao,li,wang wang,zhao,liu,li, map-------- wang:Person(name=wang, age=21, sex=female) zhao:Person(name=zhao, age=21, sex=male) liu:Person(name=liu, age=22, sex=male) li:Person(name=li, age=18, sex=female)
|
summaryStatistics 计算集合元素的最大、最小、平均等值
IntStream
、LongStream
和 DoubleStream
等流的类中,有个非常有用的方法叫做 summaryStatistics()
,可以返回 IntSummaryStatistics
、LongSummaryStatistics
或者 DoubleSummaryStatistics
,描述流中元素的各种摘要数据
1 2 3 4 5 6 7 8 9 10
| @Test public void test11(){ List<Integer> ages = Arrays.asList(2,5,3,4,7); IntSummaryStatistics statistics = ages.stream().mapToInt(e -> e).summaryStatistics(); System.out.println("最大值: " + statistics.getMax()); System.out.println("最小值: " + statistics.getMin()); System.out.println("平均值: " + statistics.getAverage()); System.out.println("总和: " + statistics.getSum()); System.out.println("个数: " + statistics.getCount()); }
|
执行结果:
1 2 3 4 5
| 最大值: 7 最小值: 2 平均值: 4.2 总和: 21 个数: 5
|