IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java高级特性第一章(Java8的流库) -> 正文阅读

[Java知识库]Java高级特性第一章(Java8的流库)

Java高级特性第一章(Java8的流库)

前言

提示:本文是OGtwelve学习高级特性时所总结内容;


1.1 流迭代

流迭代

Long count  = words.stream().filter(w -> w.length()>12).count();
//使用名为count的Long类型接收; 先获取words字符串集的流,并通过filter进行过滤(判断长度大于12的字符串)并最后进行个数统计

并行流

Long count = words.parallelStream().filter(w -> w.length()>12).count()

在上方示例中,filter会根据条件返回一条新流,count的作用是将流的个数化简为一个结果,streamparallerStream为创建,filter为转换,count为终止


流迭代总结


流的操作不会修改其数据源
例如: filter则生成新的流,不包括被滤掉的元素
(filter生成过滤后的新流并不包含过滤掉的元素)
(流的操作是惰性执行的,也就意味着找到流中最后一个元素才会执行,因此甚至可以操作无限流)

1.2 流的创建

  1. 可以用Collection接口的Stream方法将任何集合转换为一个流 , 如有数据 , 可用
    Stream<String> words = Stream.of(contents.split("//PL+"));
    of方法具有可变长参数 , 因此可以构建具有任意数量引元的流.
    [Stream接口有两个用于创建无限流的静态方法generate();方法会接收一个不包含任何引元的函数(或者从技术上讲,是一个Supplier<T>接口对象)]
  2. 使用Array.stream(array,from,to);可以用数组中的一部分元素来创建一个流.
  3. 创建不包含任何元素的流,可以用Stream.empty();方法.

常量值的流:

Stream<String> echos = stream.generate(() -> "Echo");

随机数的流:

Stream<Double> randoms = stream.generate(Math::random);

※※ 要产生(0,1,2,3…N)这样的序列,可以使用iterate方法,它会接收一个种子值,以及一个函数(准确的说是一个UnaryOpreation<T>;),并会反复地将该函数应用到之前的结果上.

例如:

Stream<BigInteger> integers = Stream.iterate(BigInteger.Zero,n -> n.add(BigInteger.One)) ;
//在该序列中,第一个元素是BigInteger.ZERO,第二个元素是f(seed),即是1(大整数BigInteger),
//下一个元素为f(f(seed),即是2;后续以此类推

※※ 如果要产生一个有限序列,则需在参数后添加一个谓词 (参数) 来描述迭代应如何结束
例如:

var limit = new Integer("10000000");
Stream<BigInteger> integers = Stream.iterate(BigInteger.Zero , n -> compareTo(limit) < 0, n -> n.add(BigInteger.One))

(只要该谓词拒绝了某个迭代生成的值 , 这个流即结束)

只传两个参数时

:(第一个值为类型,第二个值为UnaryOpreation<T>类型)

多传一位参数时

:(再多传一位时,第二个值为(lambda)表达式,之前第二个值的位置即被推到第三个值的位置.)


Stream.ofNullable方法会用一个对象来创建一个非常短的流.
如果该值判断为null,则这个流的长度为0(仅长度为0,依然存在一条流),当不为null时,长度则为1,内容即为当前判断的该对象.(与flatMap结合最适用)

注意

Java的API接口中有大量方法可以产生流 ;


示例1
例如Pattern类下有一个splitAsStream方法,会按照某个正则表达式来分割一个charSequence对象.

Pattern.compile("//PL+").splitAsStream(contents);
//contents为要分割的charSequence对象

示例2
Scanner.tokens方法会产生一个扫描器的符号流,另一种从字符串获取单词流.

Stream<String> words = new Scanner(contents).tokens();
//contents依旧为需要获取tokens的内容

示例3
静态的File.lines方法会返回一个包含了文件中所有行的Stream;

try(Stream<String> lines = File.lines(path)){
	Process lines.//处理获取到的流
}
//path在这里是文件的路径

示例4
如果持有的Iterable对象不是集合,那么可以通过下方转换为一个流

StreamSupport.stream(iterable.spliterator(),false);

如果持有的Iterable对象是集合并希望得到一个由它的结果构成的流,那么例:

StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator,spliterator.ORDERED),false);
//转换流的时候,将未知大小的分辨卸载第一个值的位置,boolean类型的判断依旧存在于句尾.

重点

  1. 在执行流的操作的时候,并没有修改流背后的集合.
  2. 流并没有收集其数据,数据一直存储在单独的集合中.
  3. 如果修改了该集合,那么流操作的结果就会变成未定义的
    (JDK文档称这种要求为不干涉性)

准确的说,因为中间流的操作是惰性的,即在终止处执行,集合有可能已经发生了变化。
(执行后原流的值被更新,差不多是一个即时时效性的问题,一般线程同步sync或平行parallel来解决 --> 括号内部分方便理解自己定义的)

1.3 filter.map和flatMap方法

流的转换会产生一个新的流,它的元素会派生自另一个流中的元素,我们已经看到了filter转换会产生一个新流,它的元素与某种条件相匹配.

1.这部分将一个字符串专户那位只包含长单词的另一个流.

List<String> words = "...";
Stream<String> longWords = words.stream().filter(w -> w.length()>12);//与1.1部分中的语句一致
//filter这的引元是Predicate<T>,即从 T 到 boolean 的函数

2.这部分将获取到的内容进行小写重组

Stream<String> lowerCaseWords = words.stream().map(String::toLowerCase);

当然在这用了map方法,通常用lambda表达式即可.

3.存入获取到内容的首字母

Stream<String> firstLetters = words.stream().map(s -> s.subString(0,1));

在使用map时,会有一个函数应用到每个元素上,并且其结果是包含了应用该函数后所产生所有结果的流。现在,假设有一个函数,返回的不是一个值,而是一个包含多个值的流。
例如:(展示的方法将字符串转换为字符串流,即一个个的编码点);

public static Stream<String> codePoints(String s){
	var result = new ArrayList<String>();
	int a = 0;
	while(i < s.length()){
		int j = s.offsetByCodePoints(i,1);
		result.add(s.subString(i,j))
		i = j;
	}
	return result.stream();
}

这个方法可以正确地处理需要用两个char值来表示Unicode字符
例如,codePoints("boat")的返回值是["b","o","a","t"];

假设

将上方方法映射到一个字符串上

Stream<Stream<String>> result = words.stream().map(w -> codePoints(w));

假如[...["A","B"],["C","D"]...]这样的流想转化为[...["A","B","C","D"]...]这样的,可以使用flatMap方法而不是map方法

Stream<String> flatResult = words.stream().flatMap(w -> codePoints(w));

★★ 在流之外也会发现有flatMap方法因为它是计算机科学中的一种通用的概念.

节后复习:
假设有一个泛型 G( 例如 Stream ),以及将某种类型 T 转换为 G<u> 的函数 f 和将类型 u 转换为 G<v> 的函数 g;
可以通过flatMap来组合它们,即首先应用f,然后应用g,那么以上即为★单子论的关键概念.

补充:

1.产生一个流,它包含当前流中所有满足谓词 (参数) 条件的元素.

Stream<T> filter(Predicate<? super T> predicate);

2.产生一个流,它包含将mapper应用于当前流中所有元素所产生的结果

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

3.产生一个流,它是通过将mapper应用于当前流中所有元素所产生的结果连接到一起而获得的
(注意,这里每一个结果都是一个流)

<R> Stream<R> flatMap(Funciton< ? super T , ? extends Stream<? extends R> > mapper)

1.4 抽取子流和组合流

1.调用stream.limit(n)会返回一个新的流,它在n个元素后结束(如果原来的流比n短,那么就会在该流结束时结束)(括号内填的大小小于整体流的大小时跳出)这个方法对于裁剪无限流的尺寸时特别有用

Stream<Double> randoms = Stream.generate(Math::random).limit(100);
//会产生一个包含100个随机数的流

2.调用`stream.skip(n)`正好相反,它会丢弃前`n`个元素,因为按照`split`的工作方式,假如第一个元素无用:
Stream<String> words = Stream.of(contents.split("//PL+")).skip(1);
//第一个元素无用时,跳过

3.stream.takeWhile(predicate)调用会在谓词 (参数) 为真true时获取流中所有元素后停止
假如使用上一部分的codePoints方法分割字符并收集;(整体和if有点相似,为true则存入)

Stream<String> initialDigits = codePoints(str).takeWhile(s ->"0...9".contain(s));
//开头包含0...9的

stream.dropWhile(predicate)则正好相反,条件为true时丢弃元素.

Stream<String> withoutInitialWhiteSpace = codePoints(str).dropWhile(s -> s.trim().length=0)
//开头为空格的,通过trim进行获取

4.可以用静态`concat`方法将两个流拼接
Stream<String> combined = Stream.concat(codePoints("Hello"),codePoints("World"));

输出则为:["H","e","l","l","o","W","o","r","l","d"] codePoints方法在1.3部分内.


抽取子流和组合流总结
Stream<T> limit(long maxSize);//产生一个流,其中包含了括号内最初的元素个数
Stream<T> skip(long n);		  //产生一个流,包含除了条件内的元素个数外的所有元素
============================================================================
Stream<T> takeWhile(Predicate<? super T> predicate);
//产生一个流,包含所有满足条件的元素
Stream<T> dropWhile(Predicate<? super T> predicate);
//产生一个流,排除不满足谓词(参数)条件的元素之外的所有元素
============================================================================
static <T> Stream<T> concat(Stream<? extends T> a , Stream<? extends T> b)
//产生一个流,它的元素是a的元素后面跟着b的元素(和一般所知的concat基本一致,不过是关于流的拼接)

结尾

以上为Java8的流库的部分特性以及示例,还没有总结完毕,后续会保持该文章持续更新。
本文多为OGtwelve学习高级特性时所总结,创作不易,点个赞点个收藏都万分感谢哦
文章与OGtwelve个人网站www.ogtwelve.com.cn保持同步更新,再次感谢大家的点赞收藏;
在未来的日子里要和各位一起熠熠生辉 Share & Learn !

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:32:20  更:2021-12-16 17:33:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:47:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码