Java8 - Stream

简介: Java8 - Stream

介绍


Java8中有两大最为重要的改变。第一个是 Lambda 表达式; 另外一个则是 Stream API(java.util.stream.*)


Stream是 Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用 Stream API 对集合数据进行操作,就类似于使用 SQL执行的数据库查询。也可以使用Stream API来并行执行操作简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。


流(Stream)到底是什么呢?


是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是致据遏进的是让算*”


注意:


Stream 自己不会存储元素。


Stream 不会改变源对象。相反,他们会返回一个持有结果的新 Stream。


Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。


生成 Stream


1/4 Collection体系集合


使用默认方法 stream() 生成流, default Stream<E> stream()


List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();


2/4 Map体系集合


把Map转成Set集合,间接的生成流


Map<String,Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();


3/4 数组


通过Arrays中的静态方法stream生成流


String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Arrays.stream(strArray);


4/4 同种数据类型的多个数据


通过Stream接口的静态方法of(T… values)生成流


Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);


Stream 流的中间操作


筛选与切片


  1. 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。


  1. filter:接收Lambda,从流中筛选出满足条件的元素。


过滤数据


// 留下满足条件的


Stream<T> filter(Predicate predicate)


Stream<T> stream = list.stream().filter(s -> s.startsWith("张"));


跳过(不要前几个)


Stream<T> skip(long n)


Stream<String> s2 = list.stream().skip(2);


截取(只取前几个)


Stream<T> limit(long maxSize)


Stream<T> stream = list.stream().limit(3);


实现分页


Integer currentPage = 3;
Integer pageSize = 10;
List<Integer> collect = list.stream().skip( (currentPage - 1) * pageSize ).limit(pageSize).collect(Collectors.toList());


合并


static Stream concat(Stream a, Stream b)


Stream.concat(s1,s2);


去重


筛选,通过流所生成元素的hashcode()和equals()去除重复元素,要想实现成功,必须实体类实现重写这两个方法


Stream distinct()


list.stream().distinct();


Stream流终结操作方法


对此流的每个元素执行操作


void forEach(Consumer action)


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


返回此流中的元素数


long count()


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


Stream流的收集操作


List<String> names = listStream.collect(Collectors.toList());
Set<Integer> set = stream.collect(Collectors.toSet());
Map<Integer, String> map = stream.collect(Collectors.toMap(s -> s, s -> 2 * s + ""));


求和


如果是 double 类型 注意会遇到精度问题。so 不建议 double 类型的用这个方法。


long sum = list.stream().mapToLong(e -> e /** 可以指定具体字段 */).sum();


List<Project> list = projectService.list(queryWrapper);
//  总投资数
Long totalInvestment = list.stream().mapToLong(Project::getTotalInvestment).sum();


实操


将集合中的某一列拿出来组合成新的集合


List<Integer> idList 
    = userList.stream().map(OrderUser::getPlatformUserId)
    .collect(Collectors.toList());


List 转 Set


Set<Integer> idSet = resourceObjectIdList.stream().collect(Collectors.toSet());


映射


map:接收Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。


flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。


List<Integer> list = Arrays.asList(13, 23, 99, 1889, 87, 1000, 88, 2, 99);
List<Integer> collect = list.stream().map(i -> i + 1).collect(Collectors.toList());
//  [14, 24, 100, 1890, 88, 1001, 89, 3, 100]


集合复制


List<CompanyChecks> checksList = //;
List<CompanyChecksNameVO> checksNameVOList = checksList.stream()
        .map(p -> {
            CompanyChecksNameVO vo = new CompanyChecksNameVO();
            BeanUtils.copyProperties(p, vo);
            return vo;
}).collect(Collectors.toList());


排序


public void test(){
    //自然排序
    List<String> list = Arrays.asList("aaa", "eee", "ddd", "bbb");
    list.stream().sorted().forEach(System.out::println);
    //定制排序
    List<Person> list1 = Arrays.asList(
            new Person("张三", 18, 2000.0),
            new Person("李四", 18, 5000.0),
            new Person("王五", 45, 8700.0),
            new Person("赵六", 42, 4200.0),
            new Person("陈七", 56, 13100.0)
    );
    list1.stream().sorted((p1,p2) -> {
        if (p1.getAge().equals(p2.getAge())){
            return p1.getSale().compareTo(p2.getSale());
        }else {
            return p1.getAge().compareTo(p2.getAge());
        }
    }).forEach(System.out::println);
}


List<Integer> list = Arrays.asList(13, 23, 99, 1889, 87, 1000, 88, 2, 99);
// 默认 顺序
List<Integer> collect = list.stream().sorted().collect(Collectors.toList());
//  [2, 13, 23, 87, 88, 99, 99, 1000, 1889]
//  定制排序:倒序
List<Integer> collect = list.stream().sorted((v1, v2) -> v2 - v1).collect(Collectors.toList());
//  [1889, 1000, 99, 99, 88, 87, 23, 13, 2]


根据特定字段排序


正序


records = records.stream()
.sorted(Comparator.comparing(StudyReview::getReviewDate))
.collect(Collectors.toList());


倒序


records = records.stream()
.sorted(Comparator.comparing(StudyReview::getReviewDate).reversed())
.collect(Collectors.toList());


多个字段排序


list.stream().sorted(Comparator.comparing(User::getAge)
                        .thenComparing(User::getId)
                        .reversed())
                .forEach(System.out::println);
相关文章
|
3月前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
107 0
|
17天前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
1月前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
37 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
1月前
|
Java Shell 流计算
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
23 1
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
|
2月前
|
存储 Java API
Java——Stream流详解
Stream流是JDK 8引入的概念,用于高效处理集合或数组数据。其API支持声明式编程,操作分为中间操作和终端操作。中间操作包括过滤、映射、排序等,可链式调用;终端操作则完成数据处理,如遍历、收集等。Stream流简化了集合与数组的操作,提升了代码的简洁性
76 11
Java——Stream流详解
|
1月前
|
存储 Java 数据处理
Flink-01 介绍Flink Java 3分钟上手 HelloWorld 和 Stream ExecutionEnvironment DataSet FlatMapFunction
Flink-01 介绍Flink Java 3分钟上手 HelloWorld 和 Stream ExecutionEnvironment DataSet FlatMapFunction
35 1
|
2月前
|
Java API C++
Java 8 Stream Api 中的 peek 操作
本文介绍了Java中`Stream`的`peek`操作,该操作通过`Consumer&lt;T&gt;`函数消费流中的每个元素,但不改变元素类型。文章详细解释了`Consumer&lt;T&gt;`接口及其使用场景,并通过示例代码展示了`peek`操作的应用。此外,还对比了`peek`与`map`的区别,帮助读者更好地理解这两种操作的不同用途。作者为码农小胖哥,原文发布于稀土掘金。
111 9
Java 8 Stream Api 中的 peek 操作
|
2月前
|
Java C# Swift
Java Stream中peek和map不为人知的秘密
本文通过一个Java Stream中的示例,探讨了`peek`方法在流式处理中的应用及其潜在问题。首先介绍了`peek`的基本定义与使用,并通过代码展示了其如何在流中对每个元素进行操作而不返回结果。接着讨论了`peek`作为中间操作的懒执行特性,强调了如果没有终端操作则不会执行的问题。文章指出,在某些情况下使用`peek`可能比`map`更简洁,但也需注意其懒执行带来的影响。
135 2
Java Stream中peek和map不为人知的秘密
|
2月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
2月前
|
Java 程序员 API
Java 8新特性之Lambda表达式与Stream API的探索
【9月更文挑战第24天】本文将深入浅出地介绍Java 8中的重要新特性——Lambda表达式和Stream API,通过实例解析其语法、用法及背后的设计哲学。我们将一探究竟,看看这些新特性如何让Java代码变得更加简洁、易读且富有表现力,同时提升程序的性能和开发效率。