java Stream使用


数据集合

ArrayList<Person> list = new ArrayList<>(10);
list.add(new Person().setId(0).setAge(10).setName("a"));
list.add(new Person().setId(1).setAge(11).setName("b"));
list.add(new Person().setId(2).setAge(12).setName("c"));
list.add(new Person().setId(3).setAge(13).setName("d"));
list.add(new Person().setId(4).setAge(14).setName("e"));
list.add(new Person().setId(5).setAge(15).setName("f"));
list.add(new Person().setId(6).setAge(16).setName("g"));
list.add(new Person().setId(7).setAge(17).setName("h"));
list.add(new Person().setId(8).setAge(18).setName("i"));
list.add(new Person().setId(9).setAge(19).setName("j"));

stream特点

  • Stream不调用终止方法,中间的操作不会执行。

stream和parallelStream的区别

  • stream 是顺序流,由主线程按顺序对流执行操作。

  • parallelStream 是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求

示例代码:

list.parallelStream().forEach(System.out::println);
System.out.println(("----------"));
list.stream().forEach(System.out::println);

运行结果:

Person(id=6, age=16, name=g)
Person(id=5, age=15, name=f)
Person(id=8, age=18, name=i)
Person(id=2, age=12, name=c)
Person(id=1, age=11, name=b)
Person(id=7, age=17, name=h)
Person(id=4, age=14, name=e)
Person(id=3, age=13, name=d)
Person(id=9, age=19, name=j)
Person(id=0, age=10, name=a)
----------
Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)
Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)

filter 过滤(中间操作)

示例代码:

list.stream().filter(person -> person.getId() > 5).forEach(System.out::println);

运行结果:

Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)
  • 满足条件的元素通过(true),不满足条件的元素会被丢弃(false)

forEach 对流进行遍历(终止操作)

示例代码:

list.stream().forEach(System.out::println); // 方法引用

运行结果:

Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)
Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)

示例代码:

list.stream().forEach(person -> System.out.print(person.getId()));

运行结果:

0123456789

limit 按给定长度截断流(中间操作)

示例代码:

list.stream().limit(5L).forEach(System.out::println);

运行结果:

Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)

map和flatMap将函数作用于每个元素(中间操作)

map和flatMap的区别
在这里插入图片描述
flatMap所用映射函数返回值必须为Stream,会将返回的Stream展开并集合起来重新串成一个新的Stream。

map所用映射函数可返回任意类型元素,直接将返回元素串起来形成一个新的Stream。

示例代码:

list.stream().flatMap(person -> {
    ArrayList<Person> append = new ArrayList<>(2);
    append.add(person);
    append.add(new Person().setId(person.getId() + 10));
    return append.stream();
}).forEach(System.out::println);

System.out.println("------------------");

list.stream().map(person -> {
    ArrayList<Person> append = new ArrayList<>(2);
    append.add(person);
    append.add(new Person().setId(person.getId() + 10));
    return append.stream();
}).forEach(System.out::println);

运行结果:

Person(id=0, age=10, name=a)
Person(id=10, age=0, name=null)
Person(id=1, age=11, name=b)
Person(id=11, age=0, name=null)
Person(id=2, age=12, name=c)
Person(id=12, age=0, name=null)
Person(id=3, age=13, name=d)
Person(id=13, age=0, name=null)
Person(id=4, age=14, name=e)
Person(id=14, age=0, name=null)
Person(id=5, age=15, name=f)
Person(id=15, age=0, name=null)
Person(id=6, age=16, name=g)
Person(id=16, age=0, name=null)
Person(id=7, age=17, name=h)
Person(id=17, age=0, name=null)
Person(id=8, age=18, name=i)
Person(id=18, age=0, name=null)
Person(id=9, age=19, name=j)
Person(id=19, age=0, name=null)
------------------
java.util.stream.ReferencePipeline$Head@6a5fc7f7
java.util.stream.ReferencePipeline$Head@3b6eb2ec
java.util.stream.ReferencePipeline$Head@1e643faf
java.util.stream.ReferencePipeline$Head@6e8dacdf
java.util.stream.ReferencePipeline$Head@7a79be86
java.util.stream.ReferencePipeline$Head@34ce8af7
java.util.stream.ReferencePipeline$Head@b684286
java.util.stream.ReferencePipeline$Head@880ec60
java.util.stream.ReferencePipeline$Head@3f3afe78
java.util.stream.ReferencePipeline$Head@7f63425a

示例代码:

System.out.println(list.stream().map(person -> 10).collect(Collectors.toList()));
System.out.println(list.stream().map(person -> "hello").collect(Collectors.toList()));

运行结果:

[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
[hello, hello, hello, hello, hello, hello, hello, hello, hello, hello]

mapToInt 函数返回值必须为int类型
flatMapToInt 函数返回值必须为IntegerSteam类型
mapToDouble 函数返回值必须为double类型
flatMapToDouble 函数返回值必须为DobuleSteam类型
mapToLong 函数返回值必须为long类型
flatMapToLong 函数返回值必须为LongStream类型

allMatch 流中所有元素都满足条件(终止操作)

示例代码:

System.out.println(list.stream().allMatch(person -> person.getId() == 5));
System.out.println(list.stream().allMatch(person -> person.getId() != 11));

输出结果:

false
true

anyMatch 流中是否有元素满足条件(终止操作)

示例代码:

System.out.println(list.stream().anyMatch(person -> person.getAge() == 11));
System.out.println(list.stream().anyMatch(person -> person.getAge() == 1));

运行结果:

true
false

noneMatch 流中没有元素满足条件(终止操作)

示例代码:

System.out.println(list.stream().noneMatch(person -> person.getId() == 5));
System.out.println(list.stream().noneMatch(person -> person.getId() == 15));

运行结果:

false
true

count 返回流的大小(终止操作)

示例代码:

System.out.println(list.stream().count());

输出结果:

10

distinct 去除重复元素(中间操作)

示例代码:

List<Integer> integerList = Arrays.asList(1, 2, 3, 3, 4, 4, 5, 6);
System.out.println(integerList.stream().distinct().collect(Collectors.toList()));

运行结果:

[1, 2, 3, 4, 5, 6]

findFirst 返回流的第一个元素(终止操作)

示例代码:

Optional<Person> optionalPerson = list.stream().findFirst();
optionalPerson.ifPresent(System.out::println);

输出结果:

Person(id=0, age=10, name=a)

findAny 返回流中任意一个元素(终止操作)

findAny操作,返回的元素是不确定的,对于同一个列表多次调用findAny()有可能会返回不同的值。使用findAny()是为了更高效的性能。如果是数据较少,串行地情况下,一般会返回第一个结果,如果是并行的情况,那就不能确保是第一个。

示例代码:

Optional<Person> optionalPerson = list.parallelStream().findAny();
optionalPerson.ifPresent(System.out::println);

运行结果:

Person(id=6, age=16, name=g)

concat 拼接两个流

示例代码:

ArrayList<Person> list2 = new ArrayList<>(2);
list2.add(new Person().setId(10).setAge(20).setName("k"));
list2.add(new Person().setId(11).setAge(21).setName("l"));
Stream<Person> stream = Stream.concat(list.stream(), list2.stream());
stream.forEach(System.out::println);

运行结果:

Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)
Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)
Person(id=10, age=20, name=k)
Person(id=11, age=21, name=l)

generate 根据提供的方法,持续生成流

示例代码:

// 如果没有limit,控制台将持续打印生成的随机数。
Stream.generate(Math::random).limit(5).forEach(System.out::println);

Stream<Double> generateB = Stream.generate(()-> Math.random()).limit(5).forEach(System.out::println);

Stream<Double> generateA = Stream.generate(new Supplier<Double>() {
    @Override
    public Double get() {
        return Math.random();
    }
}).limit(5).forEach(System.out::println);
// 三者等价,Supplier为函数接口

运行结果:

0.5137198806722759
0.6204101302224982
0.2502610330633914
0.32596750750752745
0.4628503400128364

iterate 指定种子进行迭代

示例代码:

Stream.iterate(1, item -> item + 1).limit(10).forEach(item -> System.out.print(item + "\t"));

运行结果:

1	2	3	4	5	6	7	8	9	10	

示例代码:

Stream.iterate('a', item -> (char)(item + 1)).limit(10).forEach(item -> System.out.print(item + "\t"));

运行结果:

a	b	c	d	e	f	g	h	i	j	

max和min根据提供的比较函数返回此流的最大|小元素

示例代码:

Optional<Person> optionalPerson = list.stream().max((t1, t2) -> {
    return Integer.compare(t1.getAge(), t2.getAge());
});
optionalPerson.ifPresent(System.out::println);

// 等价于
Optional<Person> optionalPerson = list.stream().max(Comparator.comparingInt(Person::getAge));
// 比较结果返回值
// 返回负整数,零或正整数,因为第一个参数小于,等于或大于第二个参数
(t1 < t2) ? -1 : ((t1 == t2) ? 0 : 1);

运行结果:

Person(id=9, age=19, name=j)

示例代码:

Optional<Person> optionalPerson = list.stream().min(Comparator.comparingInt(Person::getAge));
optionalPerson.ifPresent(System.out::println);

运行结果:

Person(id=0, age=10, name=a)

peek 将流中元素作用于函数(中间操作)

示例代码:

list.stream().peek(person -> person.setId(0)).forEach(System.out::println);

运行结果:

Person(id=0, age=10, name=a)
Person(id=0, age=11, name=b)
Person(id=0, age=12, name=c)
Person(id=0, age=13, name=d)
Person(id=0, age=14, name=e)
Person(id=0, age=15, name=f)
Person(id=0, age=16, name=g)
Person(id=0, age=17, name=h)
Person(id=0, age=18, name=i)
Person(id=0, age=19, name=j)

skip 跳过元素(中间操作)

示例代码:

list.stream().skip(5).forEach(System.out::println);

运行结果:

Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)

reduce 将流中元素结合起来得到一个值(终止操作)

方法一:
示例代码:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
stream.reduce((item1, item2) -> {
    System.out.println("item1:" + item1 + "  item2:" + item2);
    return item1 + item2;
}).ifPresent(System.out::print);
// 返回值为optional类型

运行结果:

item1:1  item2:2
item1:3  item2:3
item1:6  item2:4
item1:10  item2:5
item1:15  item2:6
item1:21  item2:7
item1:28  item2:8
item1:36  item2:9
45

方法二:
示例代码:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println(stream.reduce(10, (item1, item2) -> {
    System.out.println("item1:" + item1 + "  item2:" + item2);
    return item1 + item2;
}));
// 第一个参数必须于stream中元素的类型相同。返回值为相同元素类型

运行结果:

item1:10  item2:1
item1:11  item2:2
item1:13  item2:3
item1:16  item2:4
item1:20  item2:5
item1:25  item2:6
item1:31  item2:7
item1:38  item2:8
item1:46  item2:9
55

方法三:
示例代码:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
ArrayList<Integer> integers = new ArrayList<>();
System.out.println(stream.reduce(integers, (array, item) -> {
    System.out.println("array:" + array + "  item:" + item);
    array.add(item);
    return array;
}, (item1, item2) -> null));
// 返回值类型可以自定义

运行结果:

array:[]  item:1
array:[1]  item:2
array:[1, 2]  item:3
array:[1, 2, 3]  item:4
array:[1, 2, 3, 4]  item:5
array:[1, 2, 3, 4, 5]  item:6
array:[1, 2, 3, 4, 5, 6]  item:7
array:[1, 2, 3, 4, 5, 6, 7]  item:8
array:[1, 2, 3, 4, 5, 6, 7, 8]  item:9
[1, 2, 3, 4, 5, 6, 7, 8, 9]

第三个参数定义的规则并没有执行。这是因为reduce的第三个参数是在使用parallelStream的reduce操作时,合并各个流结果的,本例中使用的是stream,所以第三个参数是不起作用的。

toArray将流中元素封装成数组(终止操作)

示例代码:

System.out.println(list.stream().toArray());
for (Object o : list.stream().toArray()) {
    System.out.println(o);
}
System.out.println(list.stream().toArray(Person[]::new));
for (Person person : list.stream().toArray(Person[]::new)) {
    System.out.println(person);
}

运行结果:

[Ljava.lang.Object;@880ec60
Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)
Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)
[Lstream.Person;@36d64342
Person(id=0, age=10, name=a)
Person(id=1, age=11, name=b)
Person(id=2, age=12, name=c)
Person(id=3, age=13, name=d)
Person(id=4, age=14, name=e)
Person(id=5, age=15, name=f)
Person(id=6, age=16, name=g)
Person(id=7, age=17, name=h)
Person(id=8, age=18, name=i)
Person(id=9, age=19, name=j)

sorted 对流中元素进行排序(中间操作)

示例代码:

Stream<Integer> stream1 = Stream.generate(() -> new Random().nextInt(10)).limit(10);
Stream<Integer> stream2 = stream1.peek(item -> System.out.print(item + "\t"));
stream2.sorted().forEach(item -> System.out.print(item + "\t"));
// stream2.sorted(Integer::compareTo).forEach(item -> System.out.print(item + "\t"));

运行结果:

4	3	8	9	6	0	7	8	9	1 	0	1	3	4	6	7	8	8	9	9	

empty返回一个空的流

Stream<Person> stream = Stream.empty();

of 返回其元素是指定值的顺序排序流

Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(1);

builder 返回stream构造器

// 创建一个流构造器
Stream.Builder<Integer> sb = Stream.builder();
sb.accept(10);
sb.add(11);
// 构造流
Stream<Integer> stream1 = sb.build();
stream1.forEach(System.out::println);
  • 流构造之后就不能使用其accept和add方法,否则会报错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值