【问题标题】:Streams or for loops [closed]流或 for 循环 [关闭]
【发布时间】:2019-03-23 18:19:23
【问题描述】:

这个问题比较笼统,与两种风格的pros and cons 无关。 问题是我是否应该更喜欢使用 Stream 而不是 for 循环,因为它是具有良好可读性的声明式?

我正在和我的同事争论使用流和 for 循环的利弊。我同意我们应该在 90% 的时间内更喜欢流,但我相信在某些情况下使用 for 循环而不是流更好。

例如,我需要对元素集合执行多个操作,这些操作可能会引发 Checked Exception。在操作期间,如果任何元素发生异常,我想完全退出执行,所以我使用 for 循环并将其包装在 try/catch 块中。我的同事不满意,因为 result 占用的行数是 If 我使用 stream 的两倍。我通过创建自己的自定义函数接口来重写它,该接口抛出检查的异常和静态方法以将它们转换为抛出未检查的异常(示例here),最后它看起来像这样:

try {
        Map<String, String> someResult= elements.stream()
                .filter(throwingPredicateWrapper(element-> client.hasValue(element)))
                .collect(
                        Collectors.toMap(Function.identity(),
                                throwingFunctionWrapper(element -> client.getValue(element))));

        return someResult;
    } catch (Exception e) {
        LOGGER.error("Error while processing", e);
    }

他很高兴,因为它减少了两倍的代码行数。

这是一个简单的例子,看起来并没有那么糟糕,但我相信这里的旧循环是处理这种情况的更简单和更快的方法。 我们是否应该尽可能地使用 Streams?

【问题讨论】:

  • 我喜欢 for 循环......它更容易调试,但那只是我。
  • 仅供参考,您可以将 element -&gt; client.getValue(element) 替换为 client::getValue

标签: java


【解决方案1】:

“Effective Java”一书的作者 Joshua Bloch 有一个很好的 talk,它谈到了何时使用流。大约 30:30 开始观看他关于“明智地使用流”的部分。

尽管这主要是基于意见,但他认为您不想立即开始将所有程序循环转换为流,但您确实需要一种平衡的方法。他提供了至少一种示例方法,这样做会创建更难以理解的代码。他还争辩说,在许多情况下,无论是按程序编写还是以更具功能性的方式编写,都没有正确的答案,这取决于上下文(我认为团队决定以企业方式做的事情可能会发挥作用)。他在 GitHub 上有示例,以下所有示例均来自他的 GitHub 存储库

Here 是他提供的迭代字谜方法的例子,

// Prints all large anagram groups in a dictionary iteratively (Page 204)
public class IterativeAnagrams {
    public static void main(String[] args) throws IOException {
        File dictionary = new File(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);

        Map<String, Set<String>> groups = new HashMap<>();
        try (Scanner s = new Scanner(dictionary)) {
            while (s.hasNext()) {
                String word = s.next();
                groups.computeIfAbsent(alphabetize(word),
                        (unused) -> new TreeSet<>()).add(word);
            }
        }

        for (Set<String> group : groups.values())
            if (group.size() >= minGroupSize)
                System.out.println(group.size() + ": " + group);
    }

    private static String alphabetize(String s) {
        char[] a = s.toCharArray();
        Arrays.sort(a);
        return new String(a);
    }
}

here 它正在使用 Streams,

// Overuse of streams - don't do this! (page 205)
public class StreamAnagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);

        try (Stream<String> words = Files.lines(dictionary)) {
            words.collect(
                    groupingBy(word -> word.chars().sorted()
                            .collect(StringBuilder::new,
                                    (sb, c) -> sb.append((char) c),
                                    StringBuilder::append).toString()))
                    .values().stream()
                    .filter(group -> group.size() >= minGroupSize)
                    .map(group -> group.size() + ": " + group)
                    .forEach(System.out::println);
        }
    }
}

He argues 表示使用两者的平衡的第三种方法,

// Tasteful use of streams enhances clarity and conciseness (Page 205)
public class HybridAnagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);

        try (Stream<String> words = Files.lines(dictionary)) {
            words.collect(groupingBy(word -> alphabetize(word)))
                    .values().stream()
                    .filter(group -> group.size() >= minGroupSize)
                    .forEach(g -> System.out.println(g.size() + ": " + g));
        }
    }

    private static String alphabetize(String s) {
        char[] a = s.toCharArray();
        Arrays.sort(a);
        return new String(a);
    }
}

【讨论】:

  • 感谢 J. Bloch 演讲的链接。
  • 感谢@Bill 提供示例和 J.Bloch 材料链接的答案。我同意我们应该根据执行上下文和操作的复杂性来平衡方法,以提供良好的可读性和代码的纯度。
猜你喜欢
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
  • 2016-03-25
  • 2014-03-22
  • 2013-08-07
  • 2023-04-09
  • 2013-07-19
相关资源
最近更新 更多