在Java 8中使用流代替for循环

16
int [] numbers = {1,2,3,4,5,6,7,8};
int [] doubleNumbers = new int[numbers.length];
int [] tripleNumbers = new int[numbers.length];


for(int index = 0; index < numbers.length; index++)
{
    doubleNumbers[index] = numbers[index] * 2;  
    tripleNumbers[index] = numbers[index] * 3;
}

System.out.println("Double Numbers");
Arrays.stream(doubleNumbers).forEach(System.out::println);

System.out.println("Triple Numbers");
Arrays.stream(tripleNumbers).forEach(System.out::println);

我有上面的代码,在其中我使用了for循环,将数字加倍和加三倍,并在单个循环中将其存储在不同的数组中。有人能帮我使用流和map等方法编写相同的代码,而无需两次迭代数字数组。

5个回答

35
你可以这样做:

IntStream.range(0, numbers.length)
  .forEach(index -> {
    doubleNumbers[index] = numbers[index] * 2;
    tripleNumbers[index] = numbers[index] * 3;
  });

嗨Gaurav,这个选项很棒,正是我一直在寻找的,但它只适用于以上情况,如果我使用int [] numbers = {11,22,33,44,55,66,77,88}; 这个数组作为输入,它会失败并抛出异常,请问你如何解决这个问题。 - Sarang Shinde
@SarangShinde 之前有一个错误,现在已经修复了。 - thegauravmahawar

7
您可以在流内应用加倍和三倍功能:
public static void main(String[] args) {
    int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8};

    System.out.println("Double Numbers");
    Arrays.stream(numbers).map(x -> x * 2).forEach(System.out::println);

    System.out.println("Triple Numbers");
    Arrays.stream(numbers).map(x -> x * 3).forEach(System.out::println);
}

虽然从技术上讲这仍然需要迭代两次数组。
作为一个技巧,你可以收集结果到一个Map中:
Map<Integer, Integer> m = Arrays.stream(numbers)
        .boxed()
        .collect(Collectors.toMap(
                x -> x * 2,
                x -> x * 3
        ));

1
是的Jon,这是我知道的更简单、更清晰的方法,但我只希望迭代数组一次。 - Sarang Shinde
@SarangShinde,我已经编辑了我的答案,添加了另一种解决方案,避免了对数组进行两次迭代。 - jon hanson
1
迭代两次不应该是问题,因为问题的代码已经迭代了三次,所以错误已经存在于问题中。接受一个只是简单省略掉两个请求结果中的一个(除了将“times”更改为“power”)的答案来“解决”这个问题,是相当奇怪的。 - Holger

2

看起来你的问题比仅仅使用Java Stream API更为复杂。更好的方式是定义一些类似于Num.class的包装器类:

class Num {
    private final int value;

    //constructor

    public int powerOf(int index) {
        return Math.pow(value, index);
    }
}

然后您只需将数组元素包装到此对象中,并在需要时调用powerOf方法。使用您的实现方式会为保留加电值而创建不必要的数组。在这种情况下,使用Stream API更方便:

Arrays.stream(numbers).map(Num::new)
        .forEach(n -> System.out.println("power of 2": + n.powerOf(2));

感谢您的快速回复和对同一问题的不同看法。 - Sarang Shinde

1
你可以使用streamforEach方法来填充双倍和三倍的collections,例如:
public static void main(String[] args) {
    int [] numbers = {1,2,3,4,5,6,7,8};
    List<Integer> doubles = new ArrayList<Integer>();
    List<Integer> triples = new ArrayList<>();

    Arrays.stream(numbers)
    .boxed()
    .forEach(n -> {
        doubles.add(n*2);
        triples.add(n*3);
        }
    );

    System.out.println(doubles);
    System.out.println(triples);
}

另一个涉及 mapcollect 的示例:

public static void main(String[] args) {
    int [] numbers = {1,2,3,4,5,6,7,8};

    List<Integer> doubles = Arrays.stream(numbers)
    .boxed()
    .map(n -> n*2)
    .collect(Collectors.toList());

    List<Integer> triples = Arrays.stream(numbers)
            .boxed()
            .map(n -> n*3)
            .collect(Collectors.toList());

    System.out.println(doubles);
    System.out.println(triples);
}

0
你可以将每个数字表示为一个由双精度和三倍数组成的字符串数组,然后使用单个流输出这些数组。
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8};

Arrays.stream(numbers)
        // represent each number as a string
        // array of double and triple numbers
        // Stream<String[]>
        .mapToObj(i -> new String[]{
                String.valueOf(i * 2),
                String.valueOf(i * 3)})
        // reduce a stream of arrays to a single array
        .reduce((arr1, arr2) -> new String[]{
                // concatenate double numbers
                arr1[0] + " " + arr2[0],
                // concatenate triple numbers
                arr1[1] + " " + arr2[1]
        }) // output values if present
        .ifPresent(arr -> {
            System.out.println("Double numbers: " + arr[0]);
            System.out.println("Triple numbers: " + arr[1]);
        });

输出:

Double numbers: 2 4 6 8 10 12 14 16
Triple numbers: 3 6 9 12 15 18 21 24

参见:通过替换隐藏的#号生成所有可能的字符串组合

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接