天天看点

Java 8 新特性 Stream

Java 8 新特性 Stream

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,

最后由最终操作(terminal operation)得到前面处理的结果。

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+
           

以上的流程转换为 Java 代码为:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();
           

应用场景

mans 类有很多卡类,先初始化一些数据。

List<Man> mans = new ArrayList<>();
        mans.add(new Man("001","张三",Arrays.asList(new Card("工商银行","9558800001"),new Card("工商银行","9558800002"),new Card("建设银行","6227001234"))));
        mans.add(new Man("002","李四",Arrays.asList(new Card("招商银行","6225800002"),new Card("建设银行","6227035248"))));
        mans.add(new Man("003","王五",Arrays.asList(new Card("建设银行","6227056547"),new Card("中国银行","6013832547"),new Card("民生银行","4074058542"))));
        mans.add(new Man("004","赵六",Arrays.asList(new Card("工商银行","9558832458"),new Card("工商银行","9558832547"),new Card("建设银行","6227032578"))));
        mans.add(new Man("005","孙七",Arrays.asList(new Card("中国银行","6013825847"),new Card("农业银行","6228836547"),new Card("招商银行","6225014582"))));
        mans.add(new Man("006","张三",Arrays.asList(new Card("工商银行","9558832587"),new Card("交通银行","6222814578"),new Card("工商银行","9558865427"))));
           

1,查找张三的男人,for是这样的,

public List<Man> getByName(List<Man> mans){
        List<Man> temp = new ArrayList<>();
        for(Man man : mans){
            if("张三".equals(man.getName())){
                temp.add(man);
            }
        }
        return temp;
    }
           

改进后:

public List<Man> getByName8(List<Man> mans) {
        return mans.stream().filter(m -> "张三".equals(m.getName())).collect(Collectors.toList());
    }
           

这里的集合相当与数据库的表,而filter相当于数据库的where。 

filter 方法 : 用于通过设置的条件过滤出元素。

2,继续,查找id为007的男人,id唯一,for是这样的

public Man getById(List<Man> mans) {
        for (Man man : mans) {
            if ("007".equals(man.getId())) {
                return man;
            }
        }
        return null;
    }
           

改进后:

public Man getById8(List<Man> mans) {
        return mans.stream().filter(m -> "oo7".equals(m.getId())).findFirst().orElse(null);
    }
           

3,继续,获取名字叫张三(因有同名)的所有银行卡,这里不讨论实际业务意义,只讲技术,哈哈,用for是这样的。

public List<Card> getAllCardByName(List<Man> mans) {
        List<Card> cards = new ArrayList<>();
        for (Man man : mans) {
            if ("张三".equals(man.getName())) {
                cards.addAll(man.getCards());
            }
        }
        return cards;
    }
           

改进后:

public List<Card> getAllCardByName8(List<Man> mans) {
        return mans.stream().filter(m -> "张三".equals(m.getName())).flatMap(m -> m.getCards().stream())
                .collect(Collectors.toList());
    }
           

https://blog.csdn.net/weixin_41888813/article/details/82908534           Java8Stream map和flatmap的区别

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
           

4,继续,在3的条件上加个工商银行条件,for

public List<Card> getSomeCardByName(List<Man> mans) {
        List<Card> cards = new ArrayList<>();
        for (Man man : mans) {
            if ("张三".equals(man.getName())) {
                for (Card card : man.getCards()) {
                    if ("工商银行".equals(card.getName())) {
                        cards.add(card);
                    }
                }
            }
        }
        return cards;
    }
           

改进后:

public List<Card> getSomeCardByName8(List<Man> mans) {
        return mans.stream().filter(m -> "张三".equals(m.getName())).flatMap(m -> m.getCards().stream())
                .filter(c -> "工商银行".equals(c.getName())).collect(Collectors.toList());
    }
           

5,把张三的名字修改为新张三,for,注意会改变源数据

public List<Man> changeName(List<Man> mans) {
        for (Man man : mans) {
            if ("张三".equals(man.getName())) {
                man.setName("新张三");
            }
        }
        return mans;
    }
           

改进:

public List<Man> changeName8(List<Man> mans) {
        return mans.stream().peek(m -> {
            if ("张三".equals(m.getName()))
                m.setName("新张三");
        }).collect(Collectors.toList());
    }
           

实测使用peek好像会有些问题,还是直接使用forEach更加方便。 

Java 8 新特性 Stream
orElseThrow()

如果有值则将其返回,否则抛出supplier接口创建的异常。

try {
  empty.orElseThrow(()->new RuntimeException());
} catch (Throwable ex) {
  //输出: No value present in the Optional instance
  System.out.println(ex.getMessage());
}
           
案例1 :根据Age 分组,并且拆分成两个group
           
12 public class GroupByDemo {
13     public static void main(String[] args) {
14         Student student1 = new Student(200, "yangtao", "1");
15         Student student2 = new Student(220, "yangtao", "1");
16         Student student3 = new Student(500, "yangtao", "2");
17         Student student4 = new Student(504, "yangtao", "2");
18         List<Student> studentList =new ArrayList<>();
19         studentList.add(student1);
20         studentList.add(student2);
21         studentList.add(student3);
22         studentList.add(student4);
23 
24         //单一分组条件,根据code
25         Map<String, List<Student>> singleMap = studentList.stream().collect(Collectors.groupingBy(Student::getCode));
26         //{1=[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}],
27         // 2=[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}]}
28 
29         //组合分组条件
30 
31         Map<String, List<Student>> complexMap = studentList.stream().collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
32         List<Student> studentList1 = complexMap.get("yangtao+1");
33         List<Student> studentList2 = complexMap.get("yangtao+2");
34         System.out.println(complexMap);
35 //       {yangtao+2=[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}], yangtao+1=[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}]}
36 
37         System.out.println(studentList1);
38         System.out.println(studentList2);
39         //[Student{age=200, username='yangtao', code='1'}, Student{age=220, username='yangtao', code='1'}]
40         //[Student{age=500, username='yangtao', code='2'}, Student{age=504, username='yangtao', code='2'}]
41 
42     }
43     private static String fetchGroupKey(Student student){
44         return student.getUsername() +"+"+ student.getCode();
45     }
46 
47 }
           

参考来源于:

https://blog.csdn.net/williamtsang/article/details/52634970

继续阅读