当前位置:   article > 正文

Java1.8之Stream流基本使用_sortedops.348

sortedops.348

前言

Java1.8中引入了流的概念,具体实现是java.util.stream.Stream接口,流的性能是高效的,在多核CPU中,可以充分的的利用CPU资源,代码写起来也比常规的写法更简洁,在实际开发中,用得也比较多

我总结了一下Stream流的基本用法和常用方法,让我们来感受一下吧

基础

在使用流之前,需要准备三件事情:

  • 数据源
  • 中间操作链:用来形成流水线
  • 终端操作:用来生成最终结果

中间操作

操作返回类型说明使用场景
filterStream<T>返回一个由与此流匹配的元素组成的流过滤元素
mapStream<R>返回由应用给定结果组成的流类型转换
limitStream<T>返回一个被截断指定长度的流数据截取
sortedStream<T>返回由该流的元素组成的流,根据自然顺序排序 如果此流的元素不是Comparable,可能会引起ClassCastException异常数据排序
distinctStream<T>返回由不同元素组成的流数据去重

终端操作

操作返回类型说明使用场景
forEachvoid消费流中的每个元素并对其应用Lambda遍历元素
countlong返回流中元素的个数统计数量
collect<R> R把流规约成一个集合,可以是List、Map、Integer数据归约
anyMatchboolean流中元素任意一个满足判断条件数据判断
allMatchboolean流中元素全部满足判断条件数据判断

实战

MockData

在实际开发中,我们使用的更多的是DTO,所以新建一个类,再造些数据

@Data
@AllArgsConstructor
static class DTO {
    private String name;

    private Integer age;
    @Override
    public String toString() {
        return "(name=" + this.name + ", age=" + this.age + ")";
    }
}

List<DTO> list = Arrays.asList(new DTO("苹果", 20), new DTO("香蕉", 35), new DTO("橘子", 15), new DTO("芒果", 50));   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

中间操作

filter 过滤

Api:

// 返回 predicate(过滤条件) 为True的元素
Stream<T> filter(Predicate<? super T> predicate);
  • 1
  • 2

示例

// 过滤价格大于20的水果
list.stream().filter(o -> o.getPrice() > 20).forEach(System.out::println);       
  • 1
  • 2

输出如下:

(name=香蕉, price=35)
(name=芒果, price=50
  • 1
  • 2

map 类型转换

Api:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

IntStream mapToInt(ToIntFunction<? super T> mapper);

LongStream mapToLong(ToLongFunction<? super T> mapper);

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

类型转换的Api很多,这里只用map举例,其他Api用法大同小异,当我们要把类中的price转换成String或者其他类型的时候,可以这样

// 类型转换map(转换过程,需要有return) 将price转换成Double类型,并只返回Double类型的age
List<Double> collect = list.stream().map(o -> Double.valueOf(o.getPrice())).collect(Collectors.toList());
System.out.println(collect);
  • 1
  • 2
  • 3

输出如下

[20.0, 35.0, 15.0, 50.0]
  • 1

limit 数据截取

Api:

Stream<T> limit(long maxSize);
  • 1

maxSize表示返回元素的最大数量

list.stream().limit(2).forEach(System.out::println);
  • 1

输出如下

(name=苹果, price=20)
(name=香蕉, price=35)
  • 1
  • 2

sorted 数据排序

Api:

// 原生排序  如果T没有实现Comparable,会引起ClassCastException异常
Stream<T> sorted();

// 可以自定义排序规则  扩展性高
Stream<T> sorted(Comparator<? super T> comparator);
  • 1
  • 2
  • 3
  • 4
  • 5

先来看看原生排序,会发生异常:
java.lang.ClassCastException: xxxxxxx cannot be cast to java.lang.Comparable

// 排序
List<DTO> collect1 = list.stream().sorted().collect(Collectors.toList());
System.out.println(collect1);
  • 1
  • 2
  • 3

输出如下

Exception in thread "main" java.lang.ClassCastException: com.steam.T_ForeachSteam$DTO cannot be cast to java.lang.Comparable
	at java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
	at java.util.TimSort.sort(TimSort.java:220)
	at java.util.Arrays.sort(Arrays.java:1512)
	at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:348)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at com.steam.T_ForeachSteam.main(T_ForeachSteam.java:35)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

自定义排序

list.stream().sorted(Comparator.comparing(DTO::getPrice)).forEach(System.out::println);
  • 1

输出如下:

(name=橘子, price=15)
(name=苹果, price=20)
(name=香蕉, price=35)
(name=芒果, price=50)
  • 1
  • 2
  • 3
  • 4

倒序

list.stream().sorted(Comparator.comparing(DTO::getPrice).reversed()).forEach(System.out::println);
  • 1

输出如下:

(name=芒果, price=50)
(name=香蕉, price=35)
(name=苹果, price=20)
(name=橘子, price=15)
  • 1
  • 2
  • 3
  • 4

distinct 去重

Api:

// 底层是一个HashSet的实现
Stream<T> distinct()
  • 1
  • 2
List<Integer> distinctList = Arrays.asList(10, 11, 10);
distinctList.stream().distinct().forEach(o -> System.out.print(o + " "));
  • 1
  • 2

输出如下

10 11
  • 1

终端操作

count 数据计数统计

Api:

long count();
  • 1
List<String> anyMatchList = Arrays.asList("1","2","3","4","5");
long count = anyMatchList.stream().count();
System.out.println(count);
  • 1
  • 2
  • 3

输出如下

5
  • 1

allMatch anyMatch 条件返回

Api:

boolean allMatch(Predicate<? super T> predicate);
  • 1
List<String> addList = new ArrayList<>();
List<String> anyMatchList = Arrays.asList("1","2","3","4","5");
// 返回值可以理解为是否遍历了所有元素
boolean b = anyMatchList.stream().allMatch(o -> {
    addList.add(o);
    // 为false时返回
    return addList.size() < 2;
});
System.out.println(addList.toString() + b);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出如下

[1, 2]false
  • 1

Api:

boolean allMatch(Predicate<? super T> predicate);
  • 1
List<String> addList1 = new ArrayList<>();
// 返回值可以理解为是否有一个元素满足返回条件
boolean any = anyMatchList.stream().anyMatch(o -> {
    addList1.add(o);
    // 为true时返回
    return addList1.size() < 2;
});
System.out.println(addList1.toString() + any);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出如下

[1]true
  • 1

collect 数据规约

Api:

<R, A> R collect(Collector<? super T, A, R> collector);

<R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);
  • 1
  • 2
  • 3
  • 4
  • 5

使用

 List<DTO> list = Arrays.asList(new DTO("苹果", 20), new DTO("香蕉", 35),
         new DTO("菠萝", 20), new DTO("水蜜桃", 35),
         new DTO("橘子", 15), new DTO("芒果", 50));
 // 根据price分组
 Map<Integer, List<DTO>> collect = list.stream().collect(Collectors.groupingBy(DTO::getPrice));
 System.out.println(JSON.toJSONString(collect));

 // 转换成set集合
 System.out.println(Stream.of("a", "b", "c","a").collect(Collectors.toSet()));
 
 // 转换成map
 Map<String, String> collect1 = Stream.of("a", "b", "c", "a").collect(Collectors.toMap(x -> x, x -> x + x,(oldVal, newVal) -> newVal));
 collect1.forEach((k,v) -> System.out.println(k + ":" + v));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

输出如下

{50:[{"name":"芒果","price":50}],35:[{"name":"香蕉","price":35},{"name":"水蜜桃","price":35}],20:[{"name":"苹果","price":20},{"name":"菠萝","price":20}],15:[{"name":"橘子","price":15}]}
[a, b, c]
a:aa
b:bb
c:cc
  • 1
  • 2
  • 3
  • 4
  • 5

总结

Java Stream Api繁多,需要读者手动写代码感受一下。
笔者水平有限,文中有不正之处还请各位不吝指出,Stream涉及知识面广,笔者一时也无法全面叙出,文章会不定时更新和巩固,欢迎给我留言,我会在第一时间回复

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/85212
推荐阅读
相关标签
  

闽ICP备14008679号