说说在 Java 中如何创建流

1 元素转换为流

通过 Stream.of() ,我们可以很容易地将一组元素转化成流。

Stream.of("今天", "是", "个", "好日子").forEach(System.out::println);
System.out.println();
Stream.of(23, 29.2, 291.8).forEach(System.out::println);   

运行结果:

今天
是
个
好日子

23
29.2
291.8

2 集合转换为流

每种集合都可以通过调用 stream() 方法来产生一个流。 Bruce Eckel 举了这样一个示例:

List<Bubble> bubbles = Arrays.asList(new Bubble(1), new Bubble(2), new Bubble(3));
System.out.println(bubbles.stream().mapToInt(b -> b.i).sum());
System.out.println();


Set<String> set = new HashSet<>(Arrays.asList("It's a wonderful day".split(" ")));
set.stream().map(x -> x + " ").forEach(System.out::println);
System.out.println();

Map<String, Double> map = new HashMap<>();
map.put("pi", 3.14);
map.put("e", 2.71);
map.put("phi", 1.618);
map.entrySet().stream().map(e -> e.getKey() + ": " + e.getValue()).forEach(System.out::println);

运行结果:

6

a 
It's 
wonderful 
day 

phi: 1.618
e: 2.71
pi: 3.14

其中 Bubble 的定义是:

public class Bubble {
    public final int i;

    public Bubble(int i) {
        this.i = i;
    }

    @Override
    public String toString() {
        return "Bubble(" +
                "" + i +
                ')';
    }

    private static int count = 0;

    public static Bubble bubbler() {
        return new Bubble(count++);
    }
}
  1. 示例中的 mapToInt() 方法会将一个对象流(object stream)转换成为包含整型数字的 IntStream。同样,针对 Float 和 Double 也有类似名字的转换方法。
  2. 为了从 Map 集合中产生流数据,我们首先调用 entrySet() 产生一个对象流,这个对象流中的每个对象都包含一个 key 以及与其相关联的 value ,通过调用 getKey() 和 getValue() 就可以获得相应的值。
  3. 示例中的 PHI 被认为是世界上最美丽的数字。

PHI源于斐波那契数列(1-1-2-3-5-8-13-21-……)这个数列之所以非常有名,不仅是因为数列中相邻两项之和等于后一项,而且相邻的两项相除所得的商也约等于1.618。

PHI 还有一点奇妙之处是其比例与其倒数是一样的。1.618的倒数是0.618,而1.618:1与1:0.618计算结果相同。

在自然界,人们发现鹦鹉螺身上每圈罗纹的直径与相邻罗纹直径之比是 PHI。

通过连接穿过黄金分割点的弧线,就称为“黄金螺旋线”。

建筑设计上,雅典城卫城供奉庇护神雅典娜的巴特农神殿,其正立面的长与宽之比为黄金比。

据说,最早发现这个优美比例的是古希腊的毕达哥拉斯学派 . 他们曾不厌其烦地把线段 一段一段地分成不同的两截,反复改变着比例并加以比较,最后才找到了这个 “ 最优雅的比例 ”。

但是把这个比例冠以 “ 黄金 ” 二字的美名则开始于意大利著名科学家 与艺术家达芬奇。 从此,0.618作为黄金比统治着当时欧洲的建筑和艺术,并影响到人们生活的许多方面,一直延续至今。

达芬奇的《蒙娜丽莎》就是严格按照黄金比例进行设计绘制的典范。

在视觉上,黄金分割本质上带来的是和谐(相似、重复、联系),以及变化(运动、活力),通过这两点,带给人以美的享受。

3 创建数组流

可以利用 Arrays 类中的 stream() 静态方法,把数组转换为流。

Arrays.stream(new double[]{3.14, 2.71, 1.618}).forEach(n -> System.out.format("%f ", n));
System.out.println();

Arrays.stream(new int[]{3, 2, 1}).forEach(n -> System.out.format("%d ", n));
System.out.println();

Arrays.stream(new long[]{13, 12, 11}).forEach(n -> System.out.format("%d ", n));
System.out.println();

Arrays.stream(new int[]{3, 2, 1, 0, -1, -2}, 3, 6).forEach(n -> System.out.format("%d ",
        n));

运行结果:

3.140000 2.710000 1.618000 
3 2 1 
13 12 11 
0 -1 -2 

最后一个示例展示了如果设定数组范围。Arrays.stream() 方法还定义了两个额外参数。第一个参数是数组起始位置(包含),第一个参数是数组终止位置(不包含)。

4 循环遍历创建流

IntStream 类提供了 range() 方法用于生成整型序列的流。很适合编写循环:

//传统
int result = 0;
for (int i = 10; i < 20; i++) {
    result += i;
}
System.out.println(result);

//for-in 循环
result = 0;
for (int i : range(10, 20).toArray())
    result += i;
System.out.println(result);

//使用流
System.out.println(range(10, 20).sum());

运行结果:

145
145
145

第一种方式是传统编写 for 循环的方式;
第二种方式是使用 range() 创建流,接着将其转化为数组,最后在 for-in 代码块中使用;
相对来说,第三种方式最好。使用 range() 创建流之后,对流中的数字进行求和(sum)。

5 for 循环工具类

Bruce Eckel 利用 range 与 forEach 方法,实现了一个 for 循环工具类:

public class Repeat {
    public static void repeat(int n, Runnable action) {
        range(0, n).forEach(i -> action.run());
    }
}

public class Looping {
    static void hi() {
        System.out.println("Hi!");
    }

    public static void main(String[] args) {
        repeat(3, () -> System.out.println("Looping!"));
        repeat(2, Looping::hi);
    }
}

运行结果:

Looping!
Looping!
Looping!
Hi!
Hi!

该工具类让循环变得更加清晰。

6 迭代创建流

Stream.iterate() 以种子(第一个入参)作为起始值,该值会传递给 UnaryOperator(第二个入参)。UnaryOperator 的返回结果会添加到流中,并且会把结果值作为下一次迭代方法的初始入参。

我们可以利用 iterate() 生成一个斐波那契数列。

public class Fibonacci {


    int x = 1;

    Stream<Integer> numbers() {
        return Stream.iterate(0, i -> {
//            System.out.format("i -> %s\n",i);
//            System.out.format("x -> %s\n",x);
            int result = x + i;
            x = i;
//            System.out.format("result -> %s\n\n",result);
            return result;
        });
    }

    public static void main(String[] args) {
        new Fibonacci().numbers()
                .skip(20)//丢弃前 20 个
                .limit(10)//然后再取 10 个
                .forEach(System.out::println);
    }
}

运行结果:

6765
10946
17711
28657
46368
75025
121393
196418
317811
514229

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值