概述
前言
在jdk8的时候推出了Stream流,它配合上lambda表达式,可以大大简化功能的实现。如果不懂或者是没了解过Stream流的话,那么看Stream流相关的代码会很难受。但是如果真的掌握了他的用法的话,那么就只能用两个来形容,那就是:真香。
为了避免一些生硬的概念的出现,我就在下文中直接举例子,通过例子来掌握Stream流的用法。
在整个Stream流中,其实可以分为两个部分:中间操作、终端操作。下面就对这两部分相关的API来直接举例演示。
中间操作
创建一些需要举例的数据:
public class Animal {
private String name;
private int foot,age;
private BigDecimal money;
public Animal(String name, int foot, int age, BigDecimal money) {
this.name = name;
this.foot = foot;
this.age = age;
this.money = money;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getFoot() {
return foot;
}
public void setFoot(int foot) {
this.foot = foot;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
然后定义一个list集合填充对象的数值:
List<Animal> animalList = new ArrayList<Animal>() {
{
add(new Animal("dog", 4, 4, BigDecimal.valueOf(10)));
add(new Animal("cat", 4, 6,BigDecimal.valueOf(11)));
add(new Animal("duck", 2, 3,BigDecimal.valueOf(12)));
add(new Animal("chick", 2, 1,BigDecimal.valueOf(13)));
add(new Animal("pig", 4, 3,BigDecimal.valueOf(12)));
add(new Animal("horse", 4, 3,BigDecimal.valueOf(14)));
}
};
filter:过滤
他会以filter中的内容作为条件,将符合filter括号内的内容筛选过滤出来。比如我们想要得到年龄大于3的动物;
List<Animal> collect = animalList.stream()
.filter(p -> p.getAge() > 3)
.collect(Collectors.toList());
我们看下他的格式,起始是一个list集合,可以理解为数据源,然后跟了一个stream,也就是将集合转换为了流,这样的话就方便我们在后面对他进行流式处理。
filter:过滤,里面就是我们的条件,至于最后的collect,也就是收集,将前面一步得到的符合年龄大于3岁的数据收集起来作为一个list返回。
对于大部分的stream流来说,他的结构都是如此,所以在这里记得格式是这么个格式就OK。
除此之外,Stream还支持自定义过滤器、多个过滤条件。
/*找出年龄大于2,并且脚数也大于2的动物*/
Predicate<Animal> ageFilter=(p)->(p.getAge()>2);
Predicate<Animal> footFilter=(p)->(p.getFoot()>2);
List<Animal> collect = animalList.stream()
.filter(ageFilter)
.filter(footFilter)
.collect(Collectors.toList());
sort:排序
比如我想要按照年龄从小到大来进行排序,这个用stream来实现也是极为简单的:
List<Animal> collect = animalList.stream().sorted((p, p1) -> (p1.getAge() - p.getAge())).collect(Collectors.toList());
那如果从大到小呢?p和p1调个位置嘛。
ok,这是数值,可以进行减法运算,那我名字是字符,这个该怎么进行排序呢?Stream的sort也是可以对这种类型排序的:
List<Animal> collect = animalList.stream().sorted(Comparator.comparing(Animal::getName)).collect(Collectors.toList());
这个就是按照26个英文字母的顺序来进行正序排序的。如果你想按照英文字母从后向前排序,那么在comparing()后面加个reversed即可。
max、min(最大、最小值)
Stream流提供了max、min可以让我们更加方便的找出集合中的最大最小值。
集合中age最大的动物:
Animal animal = animalList
.stream()
.max((p, p1) -> p.getAge() - p1.getAge())
.get();
System.out.println(animal.getName());
因为结果是个确定的值嘛,所以使用.get()获取结果即可。.get()也是流结束的一个标志。
最小值:
Animal animal = animalList
.stream()
.min((p, p1) -> p.getAge() - p1.getAge())
.get();
System.out.println(animal.getName());
#### limit:个数限制
找到集合中前三个元素:
```java
List<Animal> collect = animalList
.stream()
.limit(3)
.collect(Collectors.toList());
collect.forEach((p)-> System.out.println(p.getName()));
map:元素映射
假如你想将集合中所有元素的某个属性放在一起,那么map将会是非常方便的方法。
获取集合中所有动物的名称:
List<String> collect = animalList.stream()
.map(Animal::getName)
.collect(Collectors.toList());
这种对象是可以以这样的形式来写的,但是对于Map来说,却无法这样实现。因为map有别的方式:
List<Map<String,Integer>> testMapList = new ArrayList<>();
testMapList.add(new HashMap(){{
put("key",1);
}});
testMapList.add(new HashMap(){{
put("key",2);
}});
List<Integer> key = testMapList.stream()
.map(p -> p.get("key"))
.collect(Collectors.toList());
distinct:去重
这个去重就很好理解了嘛,但是为了加深上面的map的印象,我们就将它们放在一起来看。
比如想找出这个集合中,共有多少个不同的年龄。
那就需要执行两步,第一步是通过map获取到集合中的所有的年龄,第二步就是执行去重。
List<Integer> collect = animalList.stream().map(Animal::getAge).distinct().collect(Collectors.toList());
limit:限制 skip:跳过
这两个放在一块展示了,因为性质其实差不多。
limit:限制取出前面n个。
skip:跳过前面n个,获取第n个后面的值,
List<Animal> collect = animalList.stream().limit(3).collect(Collectors.toList());
List<Animal> collect = animalList.stream().skip(3).collect(Collectors.toList());
summaryStatistics
如果你需要获取集合中某个属性的值的和、获取平均数之类的,那么使用summaryStatistics将会很方便:
IntSummaryStatistics intSummaryStatistics = animalList
.stream()
.mapToInt(p -> p.getAge())
.summaryStatistics();
System.out.println(intSummaryStatistics.getMax());
System.out.println(intSummaryStatistics.getMin());
System.out.println(intSummaryStatistics.getAverage());
终端操作
collect
前面我们的例子中一直以这个collect结尾,在这里我们终于要知道这个collect的用法了。前面例子中collect里面是Collectors.toList(),也就是返回值类型是一个list,除了这个Collectors.toList(),还有Collectors.toSet(),想必聪明的各位也能够猜的出来。没错,他的返回值类型就是Set。
不过除了这两个,我想介绍下Collectors.joining()。他可以将前面的流中的数据并起来。如果想把集合中的所有name并起来,并且以","作为分割,那么这个方法就派上用场了:
String collect = animalList.stream().map(Animal::getName).collect(Collectors.joining("-"));
grouping by:分组
在不用Stream流之前,感觉要对数据进行分组的话,那可老麻烦了。但是用了这个grouping by,那么就不一样了。
以年龄进行分组:
Map<Integer, List<Animal>> collect = animalList.stream().collect(Collectors.groupingBy(Animal::getAge));
而且还支持再一次分组:
Map<Integer, Map<Integer, List<Animal>>> collect = animalList.stream().collect(Collectors.groupingBy(Animal::getFoot, Collectors.groupingBy(Animal::getAge)));
看着都神清气爽,比循环分组实在是方便多了。
reduce归约
因为在开发中会对金额做处理,而金额又是BigDecimal类型的。如果要是求得集合中金额的总和,那么使用这个reduce就很方便了:
BigDecimal reduce = animalList.stream().map(p -> {
if (p.getMoney() == null) {
return BigDecimal.ZERO;
} else {
return p.getMoney();
}
}).reduce(BigDecimal.ZERO, BigDecimal::add);
它不仅支持金额相加操作,还支持相减、相乘、相除等操作。
而且,除了BigDecimal类型,对于Integer类型也是同样支持的:
Integer reduce = animalList.stream().map(Animal::getAge).reduce(0, Integer::sum);
匹配anyMatch、allMatch、nonMatch
他们三个分别为:
任意一个匹配:只要有一个符合条件,就返回true。
全部匹配:只有所有数据都符合条件时,才返回true。
没有一个匹配:只有所有数据都不符合条件时,才返回true。
用法如下:
boolean b = animalList.stream().anyMatch(p ->p.getAge()==10);
boolean b1 = animalList.stream().noneMatch(p -> p.getAge() == 10);
boolean b2 = animalList.stream().allMatch(p -> p.getAge() == 4);
总结
以上就是关于Stream流的常见用法了,我觉得可以涵盖大部分的使用场景,毕竟是一个工具类,只要多多练习,掌握它还是不难的。
最后
以上就是爱笑过客为你收集整理的一文掌握Java8Stream流的常见用法的全部内容,希望文章能够帮你解决一文掌握Java8Stream流的常见用法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复