Java8 Stream

外部迭代到内部迭代

1.首先准备POJO类,Artist

public class Artist {
    private String name;
    private String from;
    public Artist() {}
    public Artist(String name, String from) {
        this.name = name;
        this.from = from;
    }
    public String getName() {   return name;    }
    public void setName(String name) {  this.name = name;   }
    public String getFrom() {   return from;    }
    public void setFrom(String from) {  this.from = from;   }
}

2.外部迭代:Java8之前如果在处理集合时,普遍先进行迭代,然后处理返回的每一个操作。

//准备数据
List<Artist> artistList = Arrays.asList(new Artist[]{new Artist("LP", "USA"),
        new Artist("Imagine Dragon", "USA"), new Artist("Muse", "British"),
        new Artist("Sum41", "Canada"), new Artist("Simple Plan", "Canada")});

//java8之前统计USA的乐队,外部迭代
long count = 0;
for(Artist artist : artistList){
    if(artist.getFrom().equals("USA")){
        count++;
    }
}
System.out.println(count);

//高级for循环内部实现机制
count = 0;
Iterator<Artist> iterator = artistList.iterator();
while(iterator.hasNext()){
    Artist artist = iterator.next();
    if(artist.getFrom().equals("USA")){
        count++;
    }
}
System.out.println(count);

3.内部迭代:调用stream()方法,返回内部迭代的相应接口:Stream。

   Stream是用函数式编程方法在集合类上进行复杂操作的工具。

//内部迭代,通过Stream:第一步过滤出所有美国乐队,第二部统计人数
count = artistList.stream().filter(artist -> artist.getFrom().equals("USA")).count();
System.out.println(count);

4.内部迭代实现机制

a.外部迭代只有一个for循环,内部迭代分两步操作,过滤和计数,是否使用两次循环,事实上,只需循环一次。

b.Stream接口有两种类型方法,一种是惰性求值,一种是及早求值

//惰性求值
artistList.stream().filter(artist -> {
    System.out.println(artist.getName());
    return artist.getFrom().equals("USA");
});

上面filter()方法是惰性求值,filter只描述Stream,最终并不产生新的集合,运行如上代码,不会输出艺术家的名字。

判断一个操作是惰性求值还是及早求值:只需判断它的返回值。如果返回值是Stream,惰性求值。如果返回值为空或其他,那么就是及早求值。

//惰性求值加及早求值
artistList.stream().filter(artist -> {
    System.out.println(artist.getName());
    return artist.getFrom().equals("USA");
}).count();

理想的使用方式就是形成一个惰性求值的链,最后用一个及早求值的操作返回想要的结果。

5.产用的流操作

a.collect(toList())由Stream里的值产生一个列表,是及早求值的操作

//of,collect(toList())
List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList());

以上代码,首先由列表生成一个Stream,然后collect操作,由Stream生成列表。

b.map将一种类型的值转换为另外一种类型

//map(),其表达式必须为Function接口的一个实例
List<String> collected = Stream.of("a", "b", "hello").map(item -> item.toUpperCase()).collect(Collectors.toList());

c.filter遍历数据并检查其中的元素

List<String> beginWithNumbers = Stream.of("a", "1abc", "abc1").filter(value -> Character.isDigit(value.charAt(0))).collect(Collectors.toList());

d.flatMap可以用Stream替换值,然后将多个Stream连接成一个Stream

List<Integer> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4)).flatMap(numbers -> numbers.stream()).collect(Collectors.toList());

e.max和min Stream上常用的操作,求最大和最小值

List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 6, 7);
int min = numberList.stream().min(Comparator.comparing(number -> number)).get();
int max = numberList.stream().max(Comparator.comparing(number -> number)).get();

f.reduce操作

reduce操作可以对Stream()中的元素求和,0为起点,两个参数:传入Stream当前元素和acc,acc是累加器保存当前累加结果。

Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);

6.高阶函数

高阶函数是指接受另外一个函数作为参数,或返回一个函数的函数,辨认高阶函数:看函数签名,如果参数列表里包含函数接口,或者返回函数接口,就是高阶函数。

7.正确使用Lambda表达式

Lambda能够写出更简单代码,因为明确了要达成什么转化,而不是说明如何转化,这样代码潜在缺陷更少,更直接表达程序员用途。

另一层含义在于写出函数没有副作用。没有副作用的函数不会改变程序或者外界的状态。

//打印函数就是有副作用的
artistList.stream().filter(artist -> {
    System.out.println(artist.getName());
    return artist.getFrom().equals("USA");
}).count();

//赋值也是有副作用的,如下代码也不会编译通过
ActionEvent localEvent = null;
JButton jButton = new JButton().addActionListener(event ->{
    localEvent = event;
});

使用Lambda获取值而不是变量,这样也会减少错误。

转载于:https://my.oschina.net/u/2353274/blog/644231

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值