【Java基础】Java8新特性(二):Streams API及使用

Java基础学习总结(107)——Java 8 中的Streams API详解 为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对 阅读详情

引言

什么是Streams?

它不是集合元素,不是数据结构,并不保存数据

一个高级版本的迭代器(Iterator)

  1. Streams会隐式地在内部进行遍历,做出相应的数据转换
  2. 单向的,不可往复
    即数据只能遍历一次,遍历过一次后即用尽了
  3. 可以并行化操作
    parallelStream()方法,依赖于 Java7 中引入的 Fork/Join 框架来拆分任务和加速处理过程

数据源本身可以是无限的(集合是有限的)

Streams的用途?

作为一个高级版本的迭代器(Iterator),当然是用来对数据源进行遍历操作的。

疑问:遍历操作用for循环不就好了?

示例:打印与年龄超过 65 岁的买家进行交易的卖家姓名,并按姓名排序:

  • 利用for循环处理:
//找到与年龄超过 65 岁的买家进行交易的卖家
Set<Seller> sellers = new HashSet<>();
for (Txn t : txns) {
    if (t.getBuyer().getAge() >= 65)
        sellers.add(t.getSeller());
}
// 按姓名排序
List<Seller> sorted = new ArrayList<>(sellers);
Collections.sort(sorted, new Comparator<Seller>() {
    public int compare(Seller a, Seller b) {
        return a.getName().compareTo(b.getName());
    }
});
// 打印
for (Seller s : sorted)
    System.out.println(s.getName()); 
  • 利用Stream处理:
txns.stream()
    .filter(t -> t.getBuyer().getAge() >= 65)
    .map(Txn::getSeller)
    .distinct()
    .sorted(comparing(Seller::getName))
    .map(Seller::getName)
    .forEach(System.out::println);

由上示例可见:

Streams API方式的代码组织结构更清晰,可读性更强。我们只需指定“做什么”,而“如何做”交给Streams API就可以了。

从性能优化层面看:

for循环为外部迭代,其“串行”、“依次”特性使得集合框架无法对控制流进行优化。而Streams API为类库的内部迭代,类库可以进行各种优化操作(乱序执行、惰性求值、并行等),提升迭代性能。

1 Stream的组成

当我们使用一个流的时候,通常包括三个基本步骤:

  1. 获取一个数据源(source);
  2. 数据转换;
  3. 执行操作获取想要的结果。

每次转换原有 Stream 对象(数据源)不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道,如下图所示:
在这里插入图片描述
流的操作类型包括:

编号操作类型说明常见操作
1Intermediatea.其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。b.一个流可以后面跟随0个或多个 intermediate 操作。c.该类操作都是惰性化的。就是说,仅仅调用到这类方法,并没有真正开始流的遍历map (mapToInt, flatMap等)、filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered
2Terminala.一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。b.这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。c.急性操作,流的操作步骤可以理解为:数据源—惰性操作—惰性操作—急性操作forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator
3short-circuitinga.当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。b.具体的:1)、对于一个 intermediate 操作,如果它接受的是一个无限大的 Stream,但返回一个有限的新 Stream。2)、对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。anyMatch、allMatch、noneMatch、findFirst、findAny、limit

这里放一个简单的流操作示例:

int sum = widgets.stream()
				 .filter(w -> w.getColor() == RED)
 				 .mapToInt(w -> w.getWeight())
 				 .sum();

2 Stream操作详解

2.1 流的构造与转换

2.1.1 流的构造

流的构造主要有三种方式。
1 通过Stream.of()方法

		String[] nameArray = {"Tom", "Jerry"};
        Stream<String> stream = Stream.of(nameArray);

2 [Collections].stream()方法

		String[] nameArray = {"Tom", "Jerry"};
        List<String> list = Arrays.asList(nameArray);
        Stream<String> stream = list.stream();

3 数值流
对于基本数值型,目前有三种对应的包装类型 Stream:IntStream、LongStream、DoubleStream。

		IntStream.of(new int[]{1, 2, 3}).forEach(System.out::println);
		IntStream.range(1, 3).forEach(System.out::println);
		IntStream.rangeClosed(1, 3).forEach(System.out::println);

2.1.2 流的转换

流既然能通过其它的数据类型进行构造,同样的也能转换成其它的数据结构,常见的有如下三种。
1 转换成数组

		String[] toArray = stream.toArray(String[]::new);	

2 转换成集合

		// transform to List
		List<String> stringList = stream.collect(Collectors.toList());
		// transform to set
        Set<String> stringSet = stream.collect(Collectors.toSet());
        // transform to map
        Map<String, Integer> stringMap = stream.collect(Collectors.toMap(String::toUpperCase, String::length));

注意:当通过collect(Collectors.toMap())转换成Map的时候,如果出现的Key重复的情况,会报异常。

3 转换成String

 		String toString = stream.collect(Collectors.joining()).toString();

2.2 流的详细操作

map
功能:生成 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素。

		//平方数
		List<Integer> nums = Arrays.asList(1, 2, 3, 4);
		List<Integer> squareNums = nums.stream().
		map(n -> n * n).
		collect(Collectors.toList());
		 
		//转换为大写
		List<String> output = wordList.stream().
		map(String::toUpperCase).
		collect(Collectors.toList());

flatMap
功能:把 input Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一起,最终 output 的新 Stream 里面已经没有 List 了,都是直接的数字。

		 Stream<List<Integer>> inputStream = Stream.of(
		 Arrays.asList(1),
		 Arrays.asList(2, 3),
		 Arrays.asList(4, 5, 6)
		 );
		 Stream<Integer> outputStream = 
		 		inputStream.flatMap((childList) -> childList.stream());

filter
根据条件进行元素的过滤。

		 // 获取文章中的全部单词
		 List<String> output = reader.lines().
		 flatMap(line -> Stream.of(line.split(REGEXP))).
		 filter(word -> word.length() > 0).
		 collect(Collectors.toList());

forEach
功能:接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。

		//找出男性并打印姓名
		 
		//Java 8
		personlist.stream()
		 .filter(p -> p.getGender() == Person.Sex.MALE)
		 .forEach(p -> System.out.println(p.getName()));
		
		//Pre-Java 8
		for (Person p : personlist) {
		 if (p.getGender() == Person.Sex.MALE) {
		 System.out.println(p.getName());
		 }
		}

注意:forEach 不能修改自己包含的本地变量值,也不能用 break/return 之类的关键字提前结束循环。

reduce
功能: 对Stream 元素进行组合运算(提供一个起始值,然后依照BinaryOperator运算规则,和前面 Stream 的第1个、第2个、第 n 个元素组合)。

		// 字符串连接,concat = "ABCD"
		String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); 
		// 求最小值,minValue = -3.0
		double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min); 
		// 求和,sumValue = 10, 有起始值
		int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
		// 求和,sumValue = 10, 无起始值
		sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
		// 过滤,字符串连接,concat = "ace"
		concat = Stream.of("a", "B", "c", "D", "e", "F");
	 	filter(x -> x.compareTo("Z") > 0).
	 	reduce("", String::concat);

sum、min、max、average

		List<Integer> integers = Arrays.asList(1, 2, 3, 4);
		//sum操作
		Integer result = integers.stream().mapToInt(w -> w).sum();
		//等价于reduce操作
		Integer result = integers.stream().reduce(0, (a, b) -> a + b);

注意:Stream 中的reduce、max/min、findFirst、findAny等操作返回的结果类型为:Optional.

optional

  • Optional作为一个容器,它可能含有某值,或者不包含;
  • 使用它的目的是尽可能避免 NullPointerException
    在更复杂的 if (element != null) 的情况中,使用 Optional 代码的可读性更好;而且它提供的是编译时检查,能极大的降低 NPE 这种 Runtime Exception 对程序的影响,或者迫使程序员更早的在编码阶段处理空值问题,而不是留到运行时再发现和调试。

limit/skip
功能:limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素。

	public void testLimitAndSkip () {
            List<Person> persons = new ArrayList();
            for (int i = 1; i <= 10000; i++) {
                Person person = new Person(i, "name" + i);
                persons.add(person);
            }
            List<String> personList2 = persons.stream().
                    map(Person::getName).limit(10).skip(3).collect(Collectors.toList());
            System.out.println(personList2);
        }
        private class Person {
            public int no;
            private String name;

            public Person(int no, String name) {
                this.no = no;
                this.name = name;
            }

            public String getName() {
                System.out.println(name);
                return name;
            }
        }

输出:

	name1
	name2
	name3
	name4
	name5
	name6
	name7
	name8
	name9
	name10
	[name4, name5, name6, name7, name8, name9, name10]

sorted
功能:排序。比数组的排序更强之处在于你可以首先对 Stream 进行各类 map、filter、limit、skip 甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。

		//找出全文的单词,转小写,并排序
		List<String> words = br.lines().
		 	flatMap(line -> Stream.of(line.split(" "))).
		 	filter(word -> word.length() > 0).
		 	map(String::toLowerCase).
		 	distinct().
		 	sorted().
		 	collect(Collectors.toList());
		br.close();
		System.out.println(words);

Match
匹配元素,包括allMatch, anyMatch匹配等。

		List<Person> persons = new ArrayList();
		persons.add(new Person(1, "name" + 1, 10));
		persons.add(new Person(2, "name" + 2, 21));
		persons.add(new Person(3, "name" + 3, 34));
		persons.add(new Person(4, "name" + 4, 6));
		persons.add(new Person(5, "name" + 5, 55));
		//allMatch
		boolean isAllAdult = persons.stream().
		 	allMatch(p -> p.getAge() > 18);
		System.out.println(isAllAdult); // false
		//anyMatch
		boolean isThereAnyChild = persons.stream().
		 	anyMatch(p -> p.getAge() < 12);
		System.out.println(isThereAnyChild); // true
		//noneMatch
		boolean isNoChild = persons.stream().
		 	anyMatch(p -> p.getAge() > 60);
		System.out.println(isNoChild); // true

3 Guava的transform()

以Lists.transform()为例进行说明

3.1 Guava的Lists.transform()返回的结果具有“视图(View)”特性:

  • view和它所依赖的数据结构共享底层数据,当底层数据结构修改时,view会变化
  • 当view修改时(前提是view可以修改),底层数据结构也会修改
    而Stream每次转换原有Stream对象不改变,返回一个新的 Stream 对象,不修改自己所封装的底层数据结构的数据,如果希望“transform后不要返回视图,而得到独立拷贝”,StackOverflow上的建议这样:
	//返回不可变列表(推荐)
	ImmutableList.copyOf(Lists.transform(targetlist, function));    
	
	//返回可变列表
	Lists.newArrayList(Lists.transform(targetlist, function)); 

3.2 Stream进行数据结构转换更加方便

4 项目中的实例

4.1 实例1

	/**
	 * 远程加载所有区域信息,并转为不可变Map
	 *
	 * @return
	 * @throws GatewayException
	 */
	private Map<Integer, AreaInfoMsg> loadAreas() throws GatewayException {
	    Map<Integer, AreaInfoMsg> areaMap = groupGeoGateway.getAllAreas()
	            .values().stream().flatMap(List::stream)
	            .collect(Collectors.toMap(AreaInfoMsg::getId, e -> e));
	    return ImmutableMap.copyOf(areaMap);
	}
	 
	/**
	 * 获取所有区域信息
	 * @return
	 */
	public Map<Integer,List<AreaInfoMsg>> getAllAreas() throws GatewayException {
	    logger.debug("load areas from groupgeo now");
	    try {
	        return groupGeoThriftClient.mapArea();
	    } catch (TException e) {
	        throw new GatewayException("Failed loading areas from groupgeo");
	    }
	}

4.2 实例2

	//分批异步请求
	private ListenableFuture<Map<Integer, SinaiPoiModel>> innerBatchSubmit(List<Integer> manyIds) {
	    List<List<Integer>> lists = Lists.partition(manyIds, BATCH_LIMIT);
	    //分批提交,忽略单次提交异常
	    List<ListenableFuture<Map<Integer, SinaiPoiModel>>> futures = Lists.transform(lists,
	            ids -> {
	                try {
	                    return innerSubmit(ids);
	                } catch (GatewayException e) {
	                    return Futures.immediateFailedCheckedFuture(e);
	                }
	            });
	    //多次提交的结果合并为一个异步结果
	    return Futures.transform(
	            Futures.successfulAsList(futures),
	            mapList -> mapList.stream().filter(Objects::nonNull)
	                    .collect(HashMap::new, Map::putAll, Map::putAll)
	    );
	}

5 Stream的不足

  1. 遍历操作无法提前结束循环(break/return)

  2. 不支持对其元素进行直接操作或直接访问,而只支持通过声明式操作在其上进行运算然后得到结果

  3. 不推荐Web程序采用并行流(parallelStream)

List<String> names = people.parallelStream()
                           .map(Person::getName)
                           .collect(toList());

parallelStream会调用JVM内全局共享的一个 Fork/Join 框架,里面默认会启动“当前机器CPU核数”个线程。也就是说,并行流最好仅用于“纯CPU计算”——因为一旦某个网络请求把其中某个线程阻塞了,那就是JVM全局共享的“CPU核数那么多的线程”就会被阻塞。

掌握 Java 8 Streams API 2017年已经过去了。Java开发社区迎来了Java 8发布,带来了Java编程语言最新版本。Java 8引入了新的语法特性、API及工具。其中一个重要的变化就是引入了一个全新的java.util.stream包,它提供高级的函数式编程模型(functional programming model),可以使用lambda表达式编写代码。在Java 8中引入的Stream API提供了一种简单,便捷的方法用来处理数据集合。 阅读详情

相关推荐

guava-stream:用于 Guava 不可变集合的 Java 8 Stream API 收集器

用于 Guava 不可变集合的 Java 8 Stream API 收集器 在Java 8个流API,你可以收集你的要素Stream采用的的多种方法之一java.util.Collectors类。 要收集java.util.List的元素,您可以这样做: list . stream() . collect( Collectors . toList()); 但是返回的List是标准的可变 JDK List 。 那些习惯于想要返回像ImmutableList这样的不可变集合的人必须这样做: list . stream() . collect( Collectors . collectingAndThen( Collectors . toList(), ImmutableList :: copyOf)); guava-stream项目为 Guava 不可变集合提供java.util.

使用Guava轻松创建和管理不可变集合

Guava是Google推出的一个Java库,里面有一堆好用的工具类,其中就包括了不可变集合。Guava的不可变集合和咱们平时用的Java标准库集合有啥不同呢?主要是Guava的集合一旦创建,就不能被修改,这就大大减少了出错的可能性。来,让我给你演示一下怎么用Guava创建不可变集合。} }} }} }} }这段代码创建了一个包含三种水果名称的不可变列表。你看,使用就能轻松创建。这样一来,无论谁拿到这个列表,都不能添加、删除或者修改里面的元素。

宋小黑的博客 2188

Stream API函数式编程和Guava操作

Stream API常用操作,初步理解stream操作方法,对java8有初步认知。

Guava官方文档中文版(十一)-I/O工具

Guava官方文档中文版(十一)-I/O工具

dzq584462393的专栏 558

CCS20实战入门:第一个工程搭建示例

通过实际操作演示如何在ccs20中创建并配置首个开发项目,涵盖环境设置与基础调试步骤,帮助新手快速上手ccs20集成开发环境,提升嵌入式开发效率。

weixin_31185473的博客 884

STM32H743必要外围电路分析

写在前面:这篇博客是我第一次绘制STM32最小系统板的过程记录。 2020-1-11 BOOT STM32采用ARM内核,和ARM处理器一样,都有专门的boot脚决定单片机从何处启动。 在官方数据手册的第105页,我们可以看到 系统复位后,在SYSTICK的第四个上升沿锁存BOOT引脚的值,复位后,BOOT引脚可以由用户自由配置而不会影响系统正常运行。 BOOT引脚决定了自举存储器地址,当BO...

Cui_Hongwei的博客 1万+

使用guava Predicates工具类优雅处理Stream流的filter方法

现在对于集合操作时,我都是使用Stream来进行操作的,感觉贼好用,对于map操作时,一般使用方法引用就能解决,如 gradeList.stream() .map(RegionGradeViewForm::getRegionId) .map(String::valueOf) .collect(toList()); Stream流配合方法引用写的代码看着就舒服,所以用久了就不想看见箭头符号,但是在操作filter的时候,因为需要进行复杂的判断,...

qq_35634181的博客 1090

【Python 实战基础】如何绘制热力图来模拟绘制北京景区热度图

Python如何绘制热力图来模拟绘制北京景区热度图 文件读写 基础语法 字符串处理 文件生成 数据构建

菜鸟实战的博客 3401

List转Map的三种方法

for循环 、使用guava、Java8新特性Stream的Collectors类

zhangruibo_code的博客 10万+

Xilinx Vivado LDPC IP core,TSN IP core. 各种IP core

Xilinx Vivado LDPC IP core,TSN IP core. 各种IP core

qq_1432825237的博客 3991

EPSON RX8010SJ RTC实战:I2C寄存器配置避坑指南(附完整初始化代码)

本文详细解析了EPSON RX8010SJ RTC芯片在I2C寄存器配置中的常见问题与解决方案,包括TEST位、STOP位和中断控制等关键配置要点。通过实战经验分享和完整的初始化代码模板,帮助开发者避免常见陷阱,确保RTC模块的稳定运行。

weixin_28678831的博客 407

【Java8新特性】——Streams API 详解

一、为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于...

我爱吃土豆 6602

用Python+ArcGIS分析厦门共享单车数据:5分钟搞定订单时长与距离分布的可视化

本文详细介绍了如何利用Python和ArcGIS Pro 3.x快速分析厦门共享单车数据,实现订单时长与距离分布的可视化。通过数据清洗、预处理和高级可视化技巧,揭示用户行为特征,为运营优化提供数据支持。文章还提供了环境配置、代码示例和业务洞察,帮助开发者高效完成数据分析任务。

weixin_28327051的博客 337

Java 8 中的 Streams API 详解—— Streams 的背景以及 Java 8 中的使用详解

为什么需要 StreamStream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 S...

AI天才研究院 8882

〔重庆理工大学〕计算机组成原理课设报告--16位单周期CPU设计

本课程设计的实验平台为Altera Quartus II 软件和Altera Cyclone V Starter 工具箱。(1)Cyclone V是Altera FPGAs家族的一类,它面向低功耗应用。Cyclone V GX 5CGXFC5C6F27C7N 芯片有不同的转换器,按钮,LED灯,七段显示器,HDMI接口,SD卡读卡器以及其他链接等。Cyclone V GX 5CGXFC5C6F27C7N是Starter工具箱的重要组件。(2)测试台包含在测设备(DUT)和用于仿真的模拟输入。

Pretty Boy Fox的博客 1066

数字图像处理 基于matlab、opencv计算图像的梯度方向和梯度幅值

图像可以被视为标量场(即二维函数)。通过微分将标量场转换为矢量场。梯度是一个向量,描述了在x或y方向上移动时,图像变化的速度。我们使用导数来回答这样的问题,图像梯度的大小告诉图像变化的速度,而梯度的方向告诉图像变化最快的方向。因为梯度有方向和大小,所以将这些信息编码为向量是很自然的。该向量的长度提供了梯度的大小,而其方向提供了梯度方向。因为梯度在每个位置可能不同,所以我们在每个图像位置用不同的向量来表示它。

学以致用 知行合一 3202

掌握Java Streams API的使用技巧

Stream是Java 8中引入的一个新抽象,它代表可以进行一系列计算操作的元素序列。Stream并不是数据结构,它不存储数据,而是通过流水线的方式对数据进行处理。Java Streams API为处理集合数据提供了一种简洁高效的方式,通过流式编程,可以大大简化代码的编写和维护。本文详细介绍了Streams API的基本概念、常用操作和最佳实践,帮助大家更好地掌握这一强大的工具。希望本文能为您的Java编程之旅提供有价值的参考。

技术研究中心 861

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java 8 中的 Streams API 详解

文章目录Java 8 中的 Streams API 详解为什么需要 Stream什么是聚合操作Stream 总览什么是流流的构成流的使用详解流的构造与转换流的操作map/flatMapfilterforEachfindFirstreducelimit/skipsortedmin/max/distinctMatch进阶:自己生成流Stream.generateStream.iterate进阶:用 C...

松间沙路的博客 3011

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java 8 Streams 实用工具库:Streams Utils

Java 8 Streams 实用工具库:Streams Utils 项目基础介绍 Streams Utils 是一个开源项目,旨在扩展 Java 8 Stream API 的功能。它提供了一系列在标准 Java 8 Stream API 中不可用的基本操作,这些操作在一些场景中已被证明非常有用。该项目由 优快云 公司开发的 InsCode AI 大模型维护,主要使用 Java 编程语言实现。 ...

gitblog_00986的博客 469

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Java8新特性之Streams和Parallel Streams

一、Streams(流) java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如java.util.Collection 的子类,List 或者 Set, Map 不支持。Stream ...

谢小鱼的博客 1676

Java 8 Streams API 详解

Stream作为Java 8的一大亮点,它专门针对集合的各种操作提供各种非常便利,简单,高效的API,Stream API主要是通过Lambda表达式完成,极大的提高了程序的效率和可读性,同时Stram API中自带的并行流使得并发处理集合的门槛再次降低,使用Stream API编程无需多写一行多线程的大门就可以非常方便的写出高性能的并发程序。前面说到,流的中间操作是惰性的,如果一个流操作流程中只有中间操作,没有终结操作,那么这个流什么都不会做,整个流程中会一直等到遇到终结操作操作才会真正的开始执行。

D_Boat的博客 413

JDK11的新特性:HTTP API和reactive streams

在[JDK11的新特性:新的HTTP API](http://www.flydean.com/jdk11-http-api/)中,我们介绍了通过新的HTTP API,我们可以发送同步或者异步的请求,并获得的返回的结果。 今天我们想探讨一下这些同步或者异步请求和响应和reactive streams的关系。 怎么在java中使用reactive streams

程序那些事 9463

java8 streams_Java SE 8新功能介绍:使用Streams API处理集合

java8 streams 使用Java SE 8 Streams的代码更干净,易读且功能强大..... 在“ Java SE 8新功能导览”系列的这篇文章中,我们将深入解释并探索代码,以了解如何使用流遍历集合,从集合和数组创建流,聚合流值。 在上一篇文章“ Lambda的遍历,过滤,处理集合和方法增强 ”中; 我已深入探讨和探索如何使用lambda表达式和方法引用 遍历集合,使用谓词...

最佳 Java 编程 207

8个你应该掌握的实用 Java Streams API

分享8个开箱即用的API,方便日常处理集合。欢迎关注我的Java新特性专栏:https://www.didispace.com/java-features/1. 快速过滤空值:Stream.ofNullable该方法是在 Java 9 中引入的,有助于过滤集合中的所有空值,从而可能使我们避免空指针异常。在下面的示例中,有一个包含 null 的List。此时,我们可以使用Stream.ofNulla...

程序猿DD 1140

JAVA8 十大新特性详解

前言:Java8 已经发布很久了,很多报道表明Java8 是一次重大的版本升级。在Java Code Geeks上已经有很多介绍Java 8新特性的文章, 例如Playing with Java 8 – Lambdas and Concurrency、Java 8 Date Time API Tutorial : LocalDateTime和Abstract Class Versus In...

ywl470812087的博客 10万+
上一篇: 【Java基础】Java8新特性(一):lambda表达式及使用
下一篇: 【Java并发编程实战】(一):如何才能学好并发编程
少侠露飞
博客等级 码龄9年 214粉丝 117原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值