用Java 8 增加的 Stream API 能实现哪些优雅的算法

作者&投稿:崔达 (若有异议请与网页底部的电邮联系)
JDK8中增加的一个Stream接口,该接口可以将集合、数据中的元素转换为Stream流对吗?~

Java 8引入了全新的Stream API。这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同。

Stream API引入的目的在于弥补Java函数式编程的缺陷。对于很多支持函数式编程的语言,map()、reduce()基本上都内置到语言的标准库中了,不过,Java 8的Stream API总体来讲仍然是非常完善和强大,足以用很少的代码完成许多复杂的功能。

创建一个Stream有很多方法,最简单的方法是把一个Collection变成Stream。我们来看最基本的几个操作:
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream stream = numbers.stream();
stream.filter((x) -> {
return x % 2 == 0;
}).map((x) -> {
return x * x;
}).forEach(System.out::println);
}

集合类新增的stream()方法用于把一个集合变成Stream,然后,通过filter()、map()等实现Stream的变换。Stream还有一个forEach()来完成每个元素的迭代。

为什么不在集合类实现这些操作,而是定义了全新的Stream API?Oracle官方给出了几个重要原因:

一是集合类持有的所有元素都是存储在内存中的,非常巨大的集合类会占用大量的内存,而Stream的元素却是在访问的时候才被计算出来,这种“延迟计算”的特性有点类似Clojure的lazy-seq,占用内存很少。

二是集合类的迭代逻辑是调用者负责,通常是for循环,而Stream的迭代是隐含在对Stream的各种操作中,例如map()。

要理解“延迟计算”,不妨创建一个无穷大小的Stream。

如果要表示自然数集合,显然用集合类是不可能实现的,因为自然数有无穷多个。但是Stream可以做到。

自然数集合的规则非常简单,每个元素都是前一个元素的值+1,因此,自然数发生器用代码实现如下:
class NaturalSupplier implements Supplier {

long value = 0;

public Long get() {
this.value = this.value + 1;
return this.value;
}
}

反复调用get(),将得到一个无穷数列,利用这个Supplier,可以创建一个无穷的Stream:
public static void main(String[] args) {
Stream natural = Stream.generate(new NaturalSupplier());
natural.map((x) -> {
return x * x;
}).limit(10).forEach(System.out::println);
}

对这个Stream做任何map()、filter()等操作都是完全可以的,这说明Stream API对Stream进行转换并生成一个新的Stream并非实时计算,而是做了延迟计算。

当然,对这个无穷的Stream不能直接调用forEach(),这样会无限打印下去。但是我们可以利用limit()变换,把这个无穷Stream变换为有限的Stream。

利用Stream API,可以设计更加简单的数据接口。例如,生成斐波那契数列,完全可以用一个无穷流表示(受限Java的long型大小,可以改为BigInteger):
class FibonacciSupplier implements Supplier {

long a = 0;
long b = 1;

@Override
public Long get() {
long x = a + b;
a = b;
b = x;
return a;
}
}

public class FibonacciStream {

public static void main(String[] args) {
Stream fibonacci = Stream.generate(new FibonacciSupplier());
fibonacci.limit(10).forEach(System.out::println);
}
}

如果想取得数列的前10项,用limit(10),如果想取得数列的第20~30项,用:
List list = fibonacci.skip(20).limit(10).collect(Collectors.toList());

最后通过collect()方法把Stream变为List。该List存储的所有元素就已经是计算出的确定的元素了。

用Stream表示Fibonacci数列,其接口比任何其他接口定义都要来得简单灵活并且高效。

现在java8中的stream的IntStream可以方便找到数组中的最大值,而且现在stream已经把遍历内置到了jdk中,代码更整洁

通过把int数组直接转化为IntStream,然后再用内置的max方法直接求得最大值即可
示例代码如下:
int[] arr = {2,53,67,33,12,90,49};System.out.println(IntStream.of(arr).max().getAsInt());运行结果


java8的新特性stream(流)处理集合增加更多便利,同时提升了运算的效率,可以说是优雅的编程形式,把循环内置到了jdk中,只暴露了你想要什么,这种已经都是声明式编程,不再是以往的命令式编程了
想了解更多的关于stream的知识,可以去看看这篇文章
http://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

Java 8引入了全新的Stream API。这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同。

Stream API引入的目的在于弥补Java函数式编程的缺陷。对于很多支持函数式编程的语言,map()、reduce()基本上都内置到语言的标准库中了,不过,Java 8的Stream API总体来讲仍然是非常完善和强大,足以用很少的代码完成许多复杂的功能。

创建一个Stream有很多方法,最简单的方法是把一个Collection变成Stream。我们来看最基本的几个操作:
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = numbers.stream();
stream.filter((x) -> {
return x % 2 == 0;
}).map((x) -> {
return x * x;
}).forEach(System.out::println);
}

集合类新增的stream()方法用于把一个集合变成Stream,然后,通过filter()、map()等实现Stream的变换。Stream还有一个forEach()来完成每个元素的迭代。

为什么不在集合类实现这些操作,而是定义了全新的Stream API?Oracle官方给出了几个重要原因:

一是集合类持有的所有元素都是存储在内存中的,非常巨大的集合类会占用大量的内存,而Stream的元素却是在访问的时候才被计算出来,这种“延迟计算”的特性有点类似Clojure的lazy-seq,占用内存很少。

二是集合类的迭代逻辑是调用者负责,通常是for循环,而Stream的迭代是隐含在对Stream的各种操作中,例如map()。

要理解“延迟计算”,不妨创建一个无穷大小的Stream。

如果要表示自然数集合,显然用集合类是不可能实现的,因为自然数有无穷多个。但是Stream可以做到。

自然数集合的规则非常简单,每个元素都是前一个元素的值+1,因此,自然数发生器用代码实现如下:
class NaturalSupplier implements Supplier<Long> {

long value = 0;

public Long get() {
this.value = this.value + 1;
return this.value;
}
}

反复调用get(),将得到一个无穷数列,利用这个Supplier,可以创建一个无穷的Stream:
public static void main(String[] args) {
Stream<Long> natural = Stream.generate(new NaturalSupplier());
natural.map((x) -> {
return x * x;
}).limit(10).forEach(System.out::println);
}

对这个Stream做任何map()、filter()等操作都是完全可以的,这说明Stream API对Stream进行转换并生成一个新的Stream并非实时计算,而是做了延迟计算。

当然,对这个无穷的Stream不能直接调用forEach(),这样会无限打印下去。但是我们可以利用limit()变换,把这个无穷Stream变换为有限的Stream。

利用Stream API,可以设计更加简单的数据接口。例如,生成斐波那契数列,完全可以用一个无穷流表示(受限Java的long型大小,可以改为BigInteger):
class FibonacciSupplier implements Supplier<Long> {

long a = 0;
long b = 1;

@Override
public Long get() {
long x = a + b;
a = b;
b = x;
return a;
}
}

public class FibonacciStream {

public static void main(String[] args) {
Stream<Long> fibonacci = Stream.generate(new FibonacciSupplier());
fibonacci.limit(10).forEach(System.out::println);
}
}

如果想取得数列的前10项,用limit(10),如果想取得数列的第20~30项,用:
List<Long> list = fibonacci.skip(20).limit(10).collect(Collectors.toList());

最后通过collect()方法把Stream变为List。该List存储的所有元素就已经是计算出的确定的元素了。

用Stream表示Fibonacci数列,其接口比任何其他接口定义都要来得简单灵活并且高效。


黔东南苗族侗族自治州18643076620: java8提供的stream有什么用处 -
彤贵藿龙: 1. 创建Stream; 2. 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(**可以有多次转换**); 3. 对Stream进行聚合(Reduce)操作,获取想要的结果;

黔东南苗族侗族自治州18643076620: 怎样理解 Stream 的 collect 方法 -
彤贵藿龙: Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同.Stream API引入的目的在于弥补Java函数式编程的缺陷.对于很多支持函数式编程的语言,map()、reduce()基本上都内...

黔东南苗族侗族自治州18643076620: java collectors.groupingby怎么排序输出 -
彤贵藿龙: 可以用Java8的Stream来帮助生成集合,举例如下: public static void main(String[] args) { // 起始数字 int start = 1; // 生成数字的个数 int end = 100; // 生成1,2,3,4,5...100 List list = Stream.iterate(start, item -> item+1).limit(e...

黔东南苗族侗族自治州18643076620: 如何在Java 8中愉快地处理日期和时间 -
彤贵藿龙: java.util.Date是一个“万能接口”,它包含日期、时间,还有毫秒数,如果你只想用java.util.Date存储日期,或者只存储时间,那么,只有你知道哪些部分的数据是有用的,哪些部分的数据是不能用的.在新的Java 8中,日期和时间被明确划分为LocalDate和LocalTime,LocalDate无法包含时间,LocalTime无法包含日期.当然,LocalDateTime才能同时包含日期和时间.

黔东南苗族侗族自治州18643076620: Java高效打印出0000 - 9999之间所有的值存到arraylist集合中 -
彤贵藿龙: 推荐用Java8 的新特性Stream来处理 List<String> lsit = Stream.iterate(0,item->item+1) .limit(10000) .map(item -> { String str = item.toString(); while (str.length()<4) str = "0" + str; return str; }) .collect(Collectors.toList());代码简洁,易懂 Stream....

黔东南苗族侗族自治州18643076620: android如何使用lambda表达式? -
彤贵藿龙: 在Java8之前,Java并不支持Lambda表达式,而Android目前最新也才支持到Java7特性,所以在Android中使用Lambda表达式需要进行一些处理,将Lambda表达式编译成Android可以“理解”的方式.Retrolambda是一个能够让我们在Java7...

黔东南苗族侗族自治州18643076620: 照片上的问题,求解.按自然顺序排列,用java程序运行! -
彤贵藿龙: 用Java8的Stream处理很方便 Arrays.stream(kk).forEach(jj -> Arrays.sort(jj));如果以前版本的话,没有stream,就只能自己用for了 for (int k=0; k Arrays.sort(kk[k]); }个人是很不喜欢这种外部循环的...不容易并行....

黔东南苗族侗族自治州18643076620: 如何在java8中愉快地处理日期和时间java8新增了localdate和localtim -
彤贵藿龙: 看看新的LocalDate怎么用: // 取当前日期: LocalDate today = LocalDate.now(); // -> 2014-12-24 // 根据年月日取日期,12月就是12: LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25 // 根据字符串取: LocalDate endOfFeb ...

黔东南苗族侗族自治州18643076620: java8 lambda 表达式是个什么 -
彤贵藿龙: 为了支持函数式编程,Java 8引入了Lambda表达式.在Java 8中采用的是内部类来实现Lambda表达式.具体实现代码,可以通过debug看, 同时通过字节码查看工具及反编译工具来验证.自从lambda表达式成为Java语言的一部分之后,Java集...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网