订阅博客
收藏博客
微博分享
QQ空间分享

惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿

频道:民生新闻 标签:龙门客栈保时捷车标 时间:2019年10月26日 浏览:223次 评论:0条

相关于 Java8 之前的Java的相关操作简直是天差地别,Java8 的流式操作的呈现,也很大程度上改变了开发者关于Java的繁琐的操作的形象,从此,Java也走向了函数式编程的路途!

1 流的创立

1.1 流的创立办法

已然需求聊聊流的操作,那么,首要仍是先看看怎样创立流。

创立流的办法有三种,别离是: Stream.of()、Stream.iterate()、Stream.generate() ,然后,别离看一下这三个办法的声明。

static  Stream of(T... values)
static Stream iterate(T seed, UnaryOperator f)
static Stream generate(Supplier s)

Stream.of() :参数很简略,便是一系列的泛型参数。

Stream.itera濮建芳te() :第一个参数是一个初始值,第二个参数是一个操作。

Stream.generate() :参数便是一个Supplier的供应型的参数。

1.2 流的创立办法举例

/*
* @Author 欧阳思海
* @Description 创立流
* @Date 11:05 2019/8/26
* @Param []
* @return void
**/
@T病令郎的小农妻est
public 吊奶void testCreateStream() {
//运用Stream.of办法创立流
Stream安卓游戏 stream = Stream.of("hello", "world", "Java8");
stream.forEach(System.out::println);
System.out.println("##################");
//运用Stream.iterate办法创立流
Stream.iterate(10, n -> n + 1)
.limit(5)
.collect(Collectors.toList())
.forEach(System.out::println);
System.out.println("##################");
//运用Stream.generate办法创立流
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);
System.out.println("##################");
//从现有的调集中创立流
List strings = Arrays.asLi鹿兆麟st("hello", "world", "Java8");
String string = strings.stream().collect(Collectors.joining(","));
System.out.println(string);
}

在上面的比如中, Stream.of青岛cbd() 办法的参数是几个字符串, Stream.iterate() 办法的第一个参数是初始值 10,第二个参数是在10 的基础上每次加 1 的操作, Stream.generate() 的参数是用 Random 办法发生随机数。

1.3 流的创立总结

流的创立有三种办法,别离是 Stream.of()、Stream.iterate()、Stream.generate() ,这几个都是 Stream 类的静态办法,所以,运用起来十分的便利。

2 流的操作

在上一节中,咱们知道怎样创立流了,接下来,咱们就看看对流可以进行哪些操作,运用了 Stream 流之后,是否会比 Java8 之前便利许多惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿呢?

2.1 装穹顶之下箱流

在处理目标流的时分,可以运用 Collectors 类的 静态办法 转化为调集,例如,将字符串流通换为 List ,这种办法是没有问题的。

可是,假如遇到 double流想要转化为 List 时,这是就会报错。

DoubleStream.of(1.0, 2.0, 3.0)
.collect(Collectors.toList());//过错的写法

这种办法便是过错的,编译是不能经过的。

别慌,关于这种问题,有 3 种比较好的处理办法。

运用 boxed 办法

运用 boxed 办法,可以将 DoubleStream 转化为 Stream ,例如;

DoubleStream.of(1.0, 2.0, 3.0)
.boxed()
.collect(Collectors.toList());

这样就处理了上面的问题。

运用 mapToObj 办法

运用 mapToObj 办法也可以完成上面的功用,别的,也供应了 mapToInt、mapToLong、mapToDouble 等办法将根本类型流通换为相关包装类型。

DoubleStream.of(1.0, 2.0, 3.0)
.mapToObj(Double::valueOf)
.collect(Collectors.toList());

collect 办法

一般情况下,咱们运用 collect 办法的时分,都是用于将 流的数据搜集为根本类型的调集 ,例如;

stream.collect(Collectors.toList())

可是, collect 办法其实还有一种愈加一般化的办法,如下;

 R collect(Supplier supplier,
ObjIntConsumer accumulator,
BiCnsumer combiner)

上面这种办法的 第一个参数是一个供应器,相当于初始化一个容器,第二个参数是累加器,相当于给初始化的容器赋值,第三个参数是组合器,相当于将这些元素悉数组合到一个容器 。

下面,咱们经过一个简略的比如来看看到底是怎样运用的!

List list = DoubleStream.of(1.0, 2.0, 3.0)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

上面的比如咱们可以看到,第一个参数:运用一个 静态办法 初始化一个 List 容器,第二个参数:运用静态办法 add ,增加元素,第三个参数:运用静态办法 addAll ,用于联合一切的元素。

从最终的回来值为 List ,咱们也可以看出,悉数组合成一个初始化的 List 调集中了。

2.2 字符串与流之间的转化

这一末节首要解说一下字符串与流之间的转化,将 String 转为流 有两种办法,别离是 java.lang.CharSequence 接口界说的默许办法 chars 和 codePoints ,而将 流通为字符串 便是咱们前面现已解说到的办法 collect 。

/*
* @Author 欧阳思海
* @Description 字符串与流之间的转化
* @Date 9:41 2019/9/2
* @Param []
* @return void
**/
@Test
public void test惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿String2Stream() {
String s = "hello world Java8".codePoints()//转化成流
.collect(StringBuffer::n王尒可ew,
StringBuffer::appendCodePoint,
StringBuffer::append)//将流通换为字符串
.toString();
String s1 = "hello world Java8".chars()//转化成流
.collect(StringBuffer::new,
StringBuffer::appendCodePoint,
StringBuffer::append)//将流通换为字符串
.toString();
}

在上面的比如中,先用 chars 和 codePoints 办法转化为流,然后都是运用 collect 办法再转回字符串。

2.3 流的映射 map 与 flatMap

流的映射是什么意思呢,咱们先将一个在 Java8 之前的比如, 咱们常常需求将一个调集的目标的某一个字段取出来,然后再存到别的一个调集中 ,这种场景咱们在 Java8 之前咱们会这样完成。

/*
* @Author 欧阳思海
* @Description Java8之前的用法
* @Date 19:惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿31 2019/9/2
* @Param []
* @return void
**/
@Test
public void testList() {
List list = new ArrayList<>();
List friends = new ArrayList<>();
friends.add(new Friend("Java5"));
frie唯品会的东西是正品吗nds.add(new Friend("Java6"));
friends.add(new Friend("Java7"));
Person person = new Person();
person.setFriends(friends);
list.add(person);
List strings = new ArrayList<>();
for(Person p : list){
strings.add(p.getName());
}
}

是不是这样很费事,这也便是曾经咱们一向所说的 Python 用一招,Java 需求用把戏!

可是, Java8 却改变了这种实际,咱们来看一看怎样运用 map 和 flatMap 。

首要,咱们先看一下这俩个办法的 声明

 Stream map(Function
Stream flatMap(Function

接下来,咱们用这两个办法改写上面惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿的办法,先看看 map 办法;

/*
* @Author 欧阳思海
* @Description map、flatMap办法
* @Date 9:50 2019/9/2
* @Param []
* @return void
**/
@Test
public void testMapAndFlatMap() {
List list = new ArrayList<>();
List friends = new ArrayList<>();
friends.add(new Friend("Java5"));
friends.add(new Friend("Java6"));
friends.add(new Friend("Java7"));
Person person = new Person();
person.setFriends(friends);
list.add(person);
//映射出姓名
List strings = list.stream().map(Person::getName).collect(Collectors.toList());
}

经过运用 map 办法,参数给定 Person::getName 映射出 name ,然后再用 collect 搜集到 List 中,就完成了上面的担任的操作,是不是很舒畅。

可是,假如咱们用 map 办法想要映射出 friends 特点,会遇到一个问题;

//映射出朋友
List> collect = list.stream().map(Person::getFriends).collect(Collectors.toList());

咱们发现,上面的回来值是 List> ,这种办法调集里边还包着调集,处理有点费事,可是,不是还有别的 flatMap 没有运用吗,这个办法正好可以处理这个问题。

List collect1 = list.stream().flatMap(friend -> friend.getFriends().strea践组词m()).collect(Collectors.toList());

发现,这个办法的回来值是 List ,正如咱们看到的, flatMap 的办法可以“展平”包裹的流 ,这便是 map 和 flatMap 的差异。

2惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿.4 流的衔接

流的衔接有两种办法,假如是 两个流的衔接 ,运用 Stream.concat 办法,假如是 三个及三个以上的流的衔接 ,就运用 Stream.flatMap 办法。

/**
* @return void
* @Author 欧阳思海
* @Description 流的衔接
* @Date 10:13 2019/9/2
* @Param []
**/
@Test
public void testConcatStream() {
//两个流的衔接
Stream first = Stream.of("sihai", "sihai2", "sihai3");
Stream second = Stream.of("sihai4", "sihai5", "sihai6");
Stream third = Stream.of("siha7", "sihai8", "sihai9");
Stream concat = Stream.concat(first, second);
//多个流的衔接
Stream stringStream = Stream.of(first, second, third).flatMap(Function.identity());
}

3 流的规约操作

流的规约操作几种类型,这儿都讲一下。

内置的规约操作

根本类型流都有内置的规约操作。包含 average、count、max、min、sum、summaryStatistics ,前面的几个办法信任不必说了, summaryStatistics 办法是前面的几个办法的结合,下面咱们看看他们怎么运用。

/**
* @return void
* @Author 欧阳思海
* @Description 内置规约操作
* @Date 22:04 2019/9/1
* @Param []
**/
@Test
public void testRe仙居气候duce1() {
String[] strings = {"hello", "sihai", "hello", "Java8"};
long count = Arrays.stream(strings)
.map(String::length)
.count();
System.out.println(count);
System.out.println("##################");
int sum = Arrays.stream(strings)
.ma太阳系八大行星pToInt(String::length)
.sum();
System.out.println(sum);
System.out.println("##################");
OptionalDouble average = Arrays.stream(strings)
.mapToInt(String::length)
.average();
System.out.println(average);
System.out.println("##################");
OptionalInt max = Arrays.strea迷性m(strings)
.mapToInt(String::length)
.max();
System.out.println(max);
System.out.println("##################");
OptionalInt min = Arrays.stream(strings)
.mapToInt(String::length)
.min();
System.out.println(min);
DoubleSummaryStatistics statistics = DoubleStream.generate(Math::random)
.limit(1000)
.summaryStatistics();
System.out.println(statistics);
}

便是这么简略!

根本的规约操作

根本的规约操作是运用前面讲过的 reduce 办法完成的, IntStream 接口界说了三种 reduce 办法的重载办法,如下;

OptionalInt reduce(IntB车管一切人水车能洗白inaryOperator op)
int reduce(int identity, IntBianryOperator op)
U reduce(U identity,
BiFunction accumulator,
BianryOperator cabsoluteombiner)

上面的 identity 参数便是初始化值的意思, IntBianryOperator 类型的参数便是操作,例如 lambda 表达式; BianryOperator combiner 是一个组合器,在前面有讲过。

下面咱们经过一个比如来解说一下。

/**
* @return void
* @Author 欧阳思海
* @Description reduce规约操作
* @Date 22:20 2019/9/1
* @Param []
**/
@Test
public void testReduce2() {
int sum = IntStream.range(1, 20)
.reduce((x, y) -> x + y)
.orElse(0);
System.out.println(sum);
System.out.println("##################");
int sum2 = IntStream.range(1, 20)
.reduce(0, (x, y) -> x + 2 * y);
System.out.println(sum2);
System.out.println("#################惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿#");
int sum3 = IntStream.range(1, 20)
.reduce(0, Integer::sum);
System.out.println(sum3);
}

比如中的第一个是 1到20累加 的操作,第二个以 0为初始值,然后2倍累加 ,第三个是 以0为初始值,累加

流的计数

流的数量计算有两种办法,别离是 Stream.count() 办法和 Collectors.counting() 办法。

/**
* @return void
* @Author 欧阳思海
* @Description 计算测验
* @Date 23:29 2019/9/1
* @Param []
**/
@Test
public void testStatistics() {
//计算电动车价格表数量
String[] strings = {"hello", "sihai", "hello", "Java8"};
long count = Arrays.stream(strings)
.count();
System.out.println(count);
System.out.println("##################");
Long count2 = Arrays.stream(strings)
.collect(Collectors.counting());
Sy天鹅臂分化动作图片stem.out.println(count2);

}

4 流的查找与匹配

流的查找

流的查找 Stream 接口供应了两个办法 findFirst 和 findAny 。

findFirst 办法回来流中的 第一个 元素的 Optional ,而 findAny 办法回来流中的 某个元素的 Optional 。

咱们来看一个比如。

String[] strings = {"hello", "sihai", "hello", "Java8"};
Optional first = Arrays.stream(strings)
.findFirst();
System.out.println(first.get());
System.out.println("##################");
Optional any = Arrays.stream(strings).findAny();
Sy七叶一枝花stem.out.println(any.get());
System.out.println("##################");

流的匹配

流的匹配 Stream 接口供应了三个办法,别离是 anyMatch (任何一个元素匹配,回来 true)、 allMatch (一切元素匹配,回来 true)、 noneMatch (没有一个元素匹配,回来 true)。

boolean b = Stream.of(1, 2, 3, 4, 5, 10)
.any惬意,Java8 的 Stream 流式操作之王者归来,比利海灵顿Match(x -> x > 5);
System.out.println(b);
System.out.println("##################");
boolean b2 = Stream.of(1, 2, 3, 4, 5, 10)
.allMatch(x -> x > 5);
System.out.println(b2);
System.out.println("##################");
boolean b3 = Stream.of(1, 2, 3, 4, 5, 10)
.noneMatch(x -> x > 5);
System.out.println(b3);

5 流的总结

这篇文章首要解说了流的一些操作,包含下面几个周立波说湖南人凶猛方面。

  • 流的创立办法。
  • 流的系列操作,包含装箱流、字符串与流之间的转化、流和映射 map 和 flatMap、流的衔接。
  • 流的规约操作
  • 流的查找与匹配

原文

https://segmentfault.com/a/1190000020266327