- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅谈JAVA8给我带了什么——流的概念和收集器由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
到现在为止,笔者不敢给流下定义,从概念来讲他应该也是一种数据元素才是。可是在我们前面的代码例子中我们可以看到他更多的好像在表示他是一组处理数据的行为组合。这让笔者很难去理解他的定义。所以笔者不表态。各位同志自行理解吧.
在没有流以前,处理集合里面的数据一般都会用到显示的迭代器。用一下前面学生的例子吧。目标是获得学分大于5的前俩位同学.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
package
com.aomi;
import
java.util.arraylist;
import
java.util.iterator;
import
java.util.list;
import
static
java.util.stream.collectors.tolist;
public
class
main {
public
static
void
main(string[] args) {
// todo auto-generated method stub
list<student> stus = getsources();
iterator<student> ite = stus.iterator();
list<string> names =
new
arraylist<>();
int
limit =
2
;
while
(ite.hasnext() && limit >
0
) {
student stu = ite.next();
if
(stu.getscore() >
5
) {
names.add(stu.getname());
limit--;
}
}
for
(string name : names) {
system.out.println(name);
}
}
public
static
list<student> getsources() {
list<student> students =
new
arraylist<>();
student stu1 =
new
student();
stu1.setname(
"lucy"
);
stu1.setsex(
0
);
stu1.setphone(
"13700227892"
);
stu1.setscore(
9
);
student stu2 =
new
student();
stu2.setname(
"lin"
);
stu2.setsex(
1
);
stu2.setphone(
"15700227122"
);
stu2.setscore(
9
);
student stu3 =
new
student();
stu3.setname(
"lili"
);
stu3.setsex(
0
);
stu3.setphone(
"18500227892"
);
stu3.setscore(
8
);
student stu4 =
new
student();
stu4.setname(
"dark"
);
stu4.setsex(
1
);
stu4.setphone(
"16700555892"
);
stu4.setscore(
6
);
students.add(stu1);
students.add(stu2);
students.add(stu3);
students.add(stu4);
return
students;
}
}
|
如果用流的话是这样子的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
static
void
main(string[] args) {
// todo auto-generated method stub
list<student> stus = getsources();
list<string> names = stus.stream()
.filter(st -> st.getscore() >
5
)
.limit(
2
)
.map(st -> st.getname())
.collect(tolist());
for
(string name : names) {
system.out.println(name);
}
}
|
把这俩段代码相比较主要是为了说明一个概念:以前做法都是在外部迭代,最为体现就是笔者在外面定义了一个集合names 。而流却什么也没有,现在我们应该能清楚感受到流是在内部迭代。也就是说流已经帮你做好了迭代。我们只要传入相关的函数就可以得到想要的结果。至于内部迭代的好处,笔者没有办法亲身的感受,唯一的感觉就是代码变的简单明了了。但是官方说stream库为了我们在内部迭代里面做了很多优化和充公利用性能的操作。比如并行操作。所以笔者就听官方了.
事实上,在用流的过程中,我们用到很多方法函数。比如上面的limit方法,filter方法等。这个定义为流操作。但是不管是什么操作,你必须要有一个数据源吧。总结如下:
流还有一种特点——部分流操作是没有执行的。一般都是在collect函数执行的时候,才开始执行个个函数。所以我们可以细分一下流操作:
从上面的讲解我们就可以感觉流好像是先收集相关的目标操作,什么意思呢?就是先把要做的事情计划一下,最后一声令下执行。而下这个命令是collect函数。这一点跟.net的linq是很像的。同时记得他只能执行一次。也就是说这个流执行一次之后,就不可能在用了。 笔者列一下以前的用到的函数 。
foreach:终端 collect:终端 count:终端 limit:中间 filter:中间 map:中间 sorted:中间 。
到目前为止我们用到的流都是通过集合来建一个流。笔者对此从来没有讲过。现在笔者来讲些构建流的方式。 在stream库里面为我们提供了这样子一个方法——stream.of 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.aomi;
import
java.util.optional;
import
java.util.stream.stream;
public
class
main {
public
static
void
main(string[] args) {
// todo auto-generated method stub
stream stream = stream.of(
"i"
,
"am"
,
"aomi"
);
optional<string> firstword = stream.findfirst();
if
(firstword.ispresent())
{
system.out.println(
"第一个字:"
+firstword.get());
}
}
}
|
运行结果:
去看一下of方法的代码。如下 。
1
2
3
|
public
static
<t> stream<t> of(t... values) {
return
arrays.stream(values);
}
|
说明我们可能指定一个类型来建一个流。上面可以修改为 。
1
|
stream<string> stream = stream.of(
"i"
,
"am"
,
"aomi"
);
|
findfirst函数用于表示返回第一个值。那就是可能数据源是一个空呢?所以他有可以会返回null。所以就是用一个叫optional类的表示可以为空。这样子我们就可以用optional类的方法进一步做安全性的操作。比如判断有没有值(ispresent()) 笔者想要建一个int类型的数组流玩玩。为了方便笔者便试给一下上面的代码。却发现报错了.
如果我把int改为integer呢?没有问题了。所以注意要用引用类型的。int类型对应为integer类型.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.aomi;
import
java.util.optional;
import
java.util.stream.stream;
public
class
main {
public
static
void
main(string[] args) {
// todo auto-generated method stub
stream<integer> stream = stream.of(
1
,
2
,
9
);
optional<integer> firstword = stream.findfirst();
if
(firstword.ispresent())
{
system.out.println(
"第一个字:"
+firstword.get());
}
}
}
|
运行结果:
那想要用int类型呢?什么办呢?改改 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.aomi;
import
java.util.optionalint;
import
java.util.stream.intstream;
public
class
main {
public
static
void
main(string[] args) {
// todo auto-generated method stub
intstream stream = intstream.of(
1
,
2
,
9
);
optionalint firstword = stream.findfirst();
if
(firstword.ispresent())
{
system.out.println(
"第一个字:"
+firstword.getasint());
}
}
}
|
运行结果:
我们以上面的例子来一个猜测:是不是double类型,只要修改为doublestream就行呢?试试.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
com.aomi;
import
java.util.optionaldouble;
import
java.util.stream.doublestream;
public
class
main {
public
static
void
main(string[] args) {
// todo auto-generated method stub
doublestream stream = doublestream.of(
1.3
,
2.3
,
9.5
);
optionaldouble firstword = stream.findfirst();
if
(firstword.ispresent())
{
system.out.println(
"第一个字:"
+firstword.getasdouble());
}
}
}
|
运行结果:
结果很明显,我们的猜测是对的。所以见意如果你操作的流是一个int或是double的话,请进可能的用xxxstream 来建流。这样子在流的过程中不用进行拆装和封装了。必竟这是要性能的。在看一下如果数据源是一个数组的情况我们如何生成流呢?
1
2
3
4
5
6
7
8
|
public
static
collector<charsequence, ?, string> joining(charsequence delimiter,
charsequence prefix,
charsequence suffix) {
return
new
collectorimpl<>(
() ->
new
stringjoiner(delimiter, prefix, suffix),
stringjoiner::add, stringjoiner::merge,
stringjoiner::tostring, ch_noid);
}
|
在看一个叫tolist函数的代码.
1
2
3
4
5
6
|
public
static
<t>
collector<t, ?, list<t>> tolist() {
return
new
collectorimpl<>((supplier<list<t>>) arraylist::
new
, list::add,
(left, right) -> { left.addall(right);
return
left; },
ch_id);
}
|
我们发现他会共同的返回一个collector类型。从上面我们就可以知道他的任务就是用去处理最后数据。我们把他定为收集器。让我们看一下收集器的接口代码吧,
1
2
3
4
5
6
7
8
9
10
11
12
|
public
interface
collector<t, a, r> {
supplier<a> supplier();
biconsumer<a, t> accumulator();
binaryoperator<a> combiner();
function<a, r> finisher();
set<characteristics> characteristics();
}
|
光看前面四个方法是不是有一点熟悉的感觉。想要说明这个五个方法的作用。就必须明白一个概念——并行归约。前面笔者讲过流是一个内部迭代,也说stream库为我们做一个很多优化的事情。其中一个就是并行。他用到了java 7引入的功能——分支/合并框架。也就是说流会以递归的方式拆分成很多子流,然后子流可以并行执行。最后在俩俩的子流的结果合并成一个最终结果。而这俩俩合并的行为就叫归约 。如图下。引用于《java8实战》 。
我们必须根据图上的意思来走。子流的图里面会调用到collector类的三个方法.
每一个子流结束这之后,就是俩俩合并。这个时候就要看流的机制图了.
好像没有characteristics什么事情。不是这样子的。这个方法是用来说明当前这个流具备哪些优化。这样子执行流的时候,就可以很清楚的知道要以什么样子的方式执行了。比如并行。 他是一个enum类。值如下 。
由了上面的讲说明,我们在来写一个自己的收集器吧——去除相同的单词 distinctwordcollector类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package
com.aomi;
import
java.util.arraylist;
import
java.util.collections;
import
java.util.enumset;
import
java.util.list;
import
java.util.set;
import
java.util.function.biconsumer;
import
java.util.function.binaryoperator;
import
java.util.function.function;
import
java.util.function.supplier;
import
java.util.stream.collector;
public
class
distinctwordcollector
implements
collector<string, list<string>, list<string>> {
@override
public
supplier<list<string>> supplier() {
// todo auto-generated method stub
return
() ->
new
arraylist<string>();
}
/**
* 子流的处理项的过程
*/
@override
public
biconsumer<list<string>, string> accumulator() {
// todo auto-generated method stub
return
(list<string> src, string val) -> {
if
(!src.contains(val)) {
src.add(val);
}
};
}
/**
* 俩俩并合的执行函数
*/
@override
public
binaryoperator<list<string>> combiner() {
// todo auto-generated method stub
return
(list<string> src1, list<string> src2) -> {
for
(string val : src2) {
if
(!src1.contains(val)) {
src1.add(val);
}
}
return
src1;
};
}
@override
public
function<list<string>, list<string>> finisher() {
// todo auto-generated method stub
return
function.identity();
}
@override
public
set<characteristics> characteristics() {
// todo auto-generated method stub
return
collections.unmodifiableset(enumset.of(characteristics.identity_finish, characteristics.concurrent));
}
}
|
main
1
2
3
4
5
6
7
8
9
10
11
|
public
static
void
main(string[] args) {
// todo auto-generated method stub
list<string> words = arrays.aslist(
"aomi"
,
"lili"
,
"lucy"
,
"aomi"
,
"nono"
);
list<string> vals = words.stream().collect(
new
distinctwordcollector());
for
(string val : vals) {
system.out.println(val);
}
}
|
运行结果 。
结果确定就是我们想要的——去掉了重复的aomi 。
以上所述是小编给大家介绍的java8流的概念和收集器详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
最后此篇关于浅谈JAVA8给我带了什么——流的概念和收集器的文章就讲到这里了,如果你想了解更多关于浅谈JAVA8给我带了什么——流的概念和收集器的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
引用网址 http://hi.baidu.com/quiteuniverse/blog/item/9f3f043d46ad1e07bba16716.html 以下函数调用方式:&nbs
我什至不确定如何描述我正在尝试做的事情,因为我对 cookie 了解不多,但就这样吧。 是否可以使用PHP从浏览器缓存中收集一个cookie(或cookie文件),将其保存到数据库中,然后清除缓存并重
我正在使用 Room(v. 2.2.1)和协程支持(v. 1.3.2)并进行以下设置 @Entity(tableName = "simple_table") data class SimpleEnti
我正在尝试编写一个基于时间运算符收集/累积值的规则。 rule "Zone6 Overlap" when $i1 : Instance ($e1 : event == " Vel : 20.9
我有一个简单的 BST,定义了节点结构: struct node { int key_value; struct node *left; struct node *right; }; ty
我有这个对象: public class MenuPriceByDay implements Serializable { private BigDecimal avgPrice; p
我正在开发一个应用程序,需要访问给定传感器的“最后 5 秒有值(value)的数据”。我的计划是以某种方式存储这些数据,然后当我请求数据时,它将返回最近 5 秒内获得的所有数据。鉴于以下情况,我不确定
在 Ruby 中,您可以对数组使用 map/collect 方法来修改它: a = [ "a", "b", "c", "d" ] a.collect! {|x| x + "!" } a
我即将开始实时收集大量数字数据(对于那些感兴趣的人,各种股票和 future 的出价/要价/最后或“磁带”)。稍后将检索数据以进行分析和模拟。这一点都不难,但我想高效地做到这一点,这会带来很多问题。我
我提出这个问题是为了寻求有关如何设计系统的实用建议。 像 amazon.com 和 pandora 这样的网站拥有并维护着庞大的数据集来运行他们的核心业务。例如,亚马逊(以及所有其他主要电子商务网站)
假设我们有一个数据数组和另一个带索引的数组。 data = [1, 2, 3, 4, 5, 7] index = [5, 1, 4, 0, 2, 3] 我们想从 index 的 data 元素创建一个
好的,我已经阅读了几个关于它的主题,但现在就开始吧。假设我有一个应用程序,基本上我会时不时地点击一个按钮,几分钟内会发生很多事情,然后它可能会再闲置一个小时,或者可能只是 1 分钟。难道不是在整个结束
我有一个数据框,例如 Seq Chrm start end length score 0 A C1 1 50 49 12 1 B
我正在考虑在 Object[] 数组中收集泛型方法的所有方法参数以进行记录。我知道使用方面可以更好地实现这一点,但是我不允许使用它,并且如果可能的话我正在寻找一种基于纯反射的方法 为了澄清, 假设一个
快速提问: 如果 Socket 对象(及其本地缓存的 InputStream 和 OutputStream 对象)超出范围并被垃圾收集,连接是否在 JVM 中保持打开状态? (即,不会在监听服务器上抛
是否有用于收集 facebook 公共(public)数据作为实时提要的 API。我阅读了关于用于收集数据的公共(public)提要 API,但我现在不能申请,而且它不是免费的,还有 Open str
摘要 :我使用自定义收集器收集给定搜索的所有命中的文档 ID(它使用 ID 填充 BitSet)。根据我的需要,搜索和获取文档 ID 的速度非常快,但是当涉及到从磁盘实际获取文档时,事情变得非常缓慢。
我正在寻找一种方法来从自定义 Gradle 插件收集给定项目的所有依赖约束(通过常规 platform 和/或 enforcedPlatform 和/或“手动”强制执行)。 在 Maven 世界中,您
我有一个 CSV 格式的用户列表,但我需要按广告中的名称从每个用户收集 SamAccount 属性。 CSV 模型 脚本 Get-ADObject -Filter 'ObjectClass -eq "
我得到了一个非常大的列表,其中包含大约 200 个带有文本和图像的项目。 ng-repeat 是一种缓慢渲染的方式。它尝试过这个 solution 。效果很好。但不适合重复收集。 我的网络服务返回此:
我是一名优秀的程序员,十分优秀!