JAVA
Java流式编程
  • By刘立博
  • 2021-06-14 12:53:53
  • 2261人已阅读

生成流

基于值生成流

    @Test
    public void streamFromValue()
    {
        Stream<Integer> integerStream = Stream.of(1, 2, 3);
        integerStream.forEach(System.out::println);
    }

1
2
3

基于列表生成流

    @Test
    public void streamFromFile() throws IOException
    {
        Stream<String> lines = Files.lines(Paths.get("./TestSku.java"));
        lines.forEach(System.out::println);
    }

import com.alibaba.fastjson.JSON;
import org.junit.Test;
…

基于方法生成流

    @Test
    public void streamFromFunction()
    {
        Stream<Double> generate = Stream.generate(Math::random);
        generate.limit(1000).forEach(System.out::println);
    }

0.35313061918684985
0.030124447719783842
0.16394318363538818
…

操作流

 

中间操作与终端操作

中间操作:中间操作包括去重、过滤、映射等操作,值得说明的是,如果没有为流定义终端操作,为了避免无谓的计算,中间操作也不会执行

终端操作:终端产生最终的执行结果,并中断流式编程的衔接链,因此结束操作是最后一个操作.

过滤操作:filter

获取书籍栏目的sku列表

    @Test
    public void filterTest()
    {
        skuList.stream()
                .filter(skuDef -> CategoryDef.BOOK.equals(skuDef.getCategoryId()))
                .forEach(item-> System.out.println(JSON.toJSONString(item)));
    }

{"categoryId":"BOOK","price":50.23,"skuId":1,"skuName":"Electron"}
{"categoryId":"BOOK","price":30.23,"skuId":2,"skuName":"NodeJs"}
{"categoryId":"BOOK","price":150.23,"skuId":3,"skuName":"Swift"}

映射操作:map

提取sku列表中的skuName组成一个新的列表

    @Test
    public void mapTest()
    {
        skuList.stream()
                .map(SkuDef::getSkuName)
                .forEach(System.out::println);
    }

Electron
NodeJs
Swift
IP12
SWORKS
CERVELO

将列表中的对象映射成一个流:flatMap

将sku列表中的skuName对象映射为一个流

    @Test
    public void flatMapTest()
    {
        skuList.stream()
                .flatMap(sku->
                        Arrays.stream(sku.getSkuName().split(""))
                )
                .forEach(System.out::println);
    }

E
l
e
c
…

中间迭代操作:peek

与终端迭代操作forEach不同,peek不会结束流式编程

    @Test
    public void peekTest()
    {
        skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .forEach(System.out::println);
    }

Electron
SkuDef(skuId=1, categoryId=BOOK, skuName=Electron, price=50.23)
NodeJs
SkuDef(skuId=2, categoryId=BOOK, skuName=NodeJs, price=30.23)
…

排序操作:sorted

根据价格对列表中的sku进行排序

    @Test
    public void sortTest()
    {
        skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .sorted(Comparator.comparing(SkuDef::getPrice))
                .forEach(System.out::println);
    }

Electron
NodeJs
Swift
IP12
SWORKS
CERVELO
SkuDef(skuId=2, categoryId=BOOK, skuName=NodeJs, price=30.23)
SkuDef(skuId=1, categoryId=BOOK, skuName=Electron, price=50.23)
SkuDef(skuId=3, categoryId=BOOK, skuName=Swift, price=150.23)
SkuDef(skuId=4, categoryId=APPLE, skuName=IP12, price=5150.23)
SkuDef(skuId=6, categoryId=SPORTS, skuName=CERVELO, price=15150.23)
SkuDef(skuId=5, categoryId=SPORTS, skuName=SWORKS, price=25150.23)

去重操作:distinct

去掉sku列表中重复的栏目id

    @Test
    public void distinctTest()
    {
        skuList.stream()
                .map(SkuDef::getCategoryId)
                .distinct()
                .forEach(System.out::println);
    }

BOOK
APPLE
SPORTS

跳过前N条记录:skip

排序后迭代sku列表跳过前3条记录

    @Test
    public void skipTest()
    {
        skuList.stream()
                .sorted(Comparator.comparing(SkuDef::getPrice))
                .skip(3)
                .forEach(System.out::println);
    }

SkuDef(skuId=4, categoryId=APPLE, skuName=IP12, price=5150.23)
SkuDef(skuId=6, categoryId=SPORTS, skuName=CERVELO, price=15150.23)
SkuDef(skuId=5, categoryId=SPORTS, skuName=SWORKS, price=25150.23)

约束操作:limit

排序后迭代sku列表,跳过前3条记录后,返回1条记录

    @Test
    public void limitTest()
    {
        skuList.stream()
                .sorted(Comparator.comparing(SkuDef::getPrice))
                .skip(3)
                .limit(1)
                .forEach(System.out::println);
    }

SkuDef(skuId=4, categoryId=APPLE, skuName=IP12, price=5150.23)

匹配操作:allMatch

终端操作,所有元素都满足条件时返回ture,否则返回false

    @Test
    public void allMatchTest()
    {
        boolean b = skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .allMatch(skuDef -> skuDef.getPrice().compareTo(new BigDecimal(10)) > 0);
        System.out.println(b);

    }

Electron
NodeJs
Swift
IP12
SWORKS
CERVELO
true

匹配操作:noneMatch

终端操作,所有元素都不匹配时,返回true

    @Test
    public void noneMatchTest()
    {
        boolean b = skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .noneMatch(skuDef -> skuDef.getSkuId() < 1);
        System.out.println(b);
    }

Electron
NodeJs
Swift
IP12
SWORKS
CERVELO
true

查找操作:findFirst

找出列表中第一个对象

    @Test
    public void findFirstTest()
    {
        Optional<SkuDef> first = skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .findFirst();
        System.out.println(JSON.toJSONString(first.get(),true));
    }

Electron
{
	"categoryId":"BOOK",
	"price":50.23,
	"skuId":1,
	"skuName":"Electron"
}

查找操作:findAny

找出列表中任意一个对象

    @Test
    public void findAnyTest()
    {
        Optional<SkuDef> first = skuList.stream()
                .peek(skuDef -> System.out.println(skuDef.getSkuName()))
                .findAny();
        System.out.println(JSON.toJSONString(first.get(),true));
    }

Electron
{
	"categoryId":"BOOK",
	"price":50.23,
	"skuId":1,
	"skuName":"Electron"
}

查找操作:max

找出列表中skuId最大的对象

    @Test
    public void maxTest()
    {
        OptionalInt max = skuList.stream()
                .mapToInt(SkuDef::getSkuId).max();
        System.out.println(max.getAsInt());
    }

6

查找操作:min

找出列表中skuId最小的对象

    @Test
    public void minTest()
    {
        OptionalInt max = skuList.stream()
                .mapToInt(SkuDef::getSkuId).min();
        System.out.println(max.getAsInt());
    }

1

统计操作:count

统计列表中对象个数

    @Test
    public void countTest()
    {
        long count = skuList.stream().count();
        System.out.println(count);
    }

6

收集流

可以使用Collectors方法作为终端操作,将流生成的数据收集起来,供下阶段使用

 

集合收集

收集Sku列表中id大于3的sku

    @Test
    public void testCollectorsList()
    {
        List<SkuDef> skuList = new SkuService().getSkuList();
        List<SkuDef> collect = skuList.stream()
                .filter(skuDef -> skuDef.getSkuId() > 3)
                .collect(Collectors.toList());

        System.out.println(JSON.toJSONString(collect,true));
    }

[
	{
		"categoryId":"APPLE",
		"price":5150.23,
		"skuId":4,
		"skuName":"IP12"
	},
	{
		"categoryId":"SPORTS",
		"price":25150.23,
		"skuId":5,
		"skuName":"SWORKS"
	},
	{
		"categoryId":"SPORTS",
		"price":15150.23,
		"skuId":6,
		"skuName":"CERVELO"
	}
]

分组收集

按栏目id收集sku列表

    @Test
    public void testGroup()
    {
        List<SkuDef> skuList = new SkuService().getSkuList();

        Map<CategoryDef, List<SkuDef>> collect = skuList.stream()
                .collect(Collectors.groupingBy(SkuDef::getCategoryId));

        System.out.println(JSON.toJSONString(collect,true));
    }

{"APPLE":[
		{
			"categoryId":"APPLE",
			"price":5150.23,
			"skuId":4,
			"skuName":"IP12"
		}
	],"SPORTS":[
		{
			"categoryId":"SPORTS",
			"price":25150.23,
			"skuId":5,
			"skuName":"SWORKS"
		},
		{
			"categoryId":"SPORTS",
			"price":15150.23,
			"skuId":6,
			"skuName":"CERVELO"
		}
	],"BOOK":[
		{
			"categoryId":"BOOK",
			"price":50.23,
			"skuId":1,
			"skuName":"Electron"
		},
		{
			"categoryId":"BOOK",
			"price":30.23,
			"skuId":2,
			"skuName":"NodeJs"
		},
		{
			"categoryId":"BOOK",
			"price":150.23,
			"skuId":3,
			"skuName":"Swift"
		}
	]
}

分区收集

收集skuId大于3和不大于3的sku列表

    @Test
    public void partitionTest()
    {
        List<SkuDef> skuList = new SkuService().getSkuList();

        Map<Boolean, List<SkuDef>> collect = skuList.stream()
                .collect(Collectors.partitioningBy(skuDef -> skuDef.getSkuId() > 3));

        System.out.println(JSON.toJSONString(collect,true));
    }