如何跳过Java流中的连续元素?

问题描述 投票:0回答:2

我一直在尝试将更多的函数式编程融入到我所做的事情中,因为我编写的代码具有无副作用的性质及其在并发代码中的实用性。我遇到了过滤 Java 流的连续元素的需要,并且无法想出比普通的旧命令式方法更好的功能方法。

假设我有一个记录其参数的程序,并且我想过滤掉两个连续的元素。 例如,

-o anOption, -k aSecretKeyWhoseValueWeShouldNotLog, -a anotherOption
。 我想要的日志是
-o anOption, -a anotherOption

我想出了几种方法,但没有一种比使用 for 循环更容易理解,该循环索引了我需要过滤掉的内容。

这似乎是一件相当普遍的事情。 是否有一种使用 Java 流或其他任何东西的模式,通常用于此类事情?

这就是我的最终结果:

static String filterSecretKeyOutOfCommandLineLogString(final String[] args) {
    return joinArgsToString(filterOptionAndValueOutOfCommandLineLogString(SECRET_KEY, args));
}

private static String joinArgsToString(final String[] args) {
    return Joiner.on(ARG_JOINER_DELIMITER).join(args);
}

private static String[] filterOptionAndValueOutOfCommandLineLogString(final Option option, final String[] args) {
    final List<String> filteredList = new ArrayList<>();

    final int numArgs = args.length;

    for (int i = 0; i < numArgs; ++i) {
        if (Arguments.matchesOption(option, args[i])) {
            ++i;
         } else {
             filteredList.add(args[i]);
         }
     }

     return filteredList.toArray(new String[0]);
}
java java-8 functional-programming java-stream
2个回答
5
投票

我不确定这是否比您已有的更好。假设输入是

String[]
并且您想要的(中间)输出也是
String[]
,对 Java 流的简单翻译可能是

static String[] filterOptionAndValue(String option, String args[]) {
    return IntStream.range(0, args.length)
            .filter(i -> i % 2 == 0)
            .mapToObj(i -> new AbstractMap.SimpleEntry<>(args[i], args[i + 1]))
            .filter(e -> !option.equals(e.getKey()))
            .flatMap(e -> Stream.of(e.getKey(), e.getValue()))
            .toArray(String[]::new);
}

public static void main(String... env) {

    String[] args = {"-o", "opt1", "-k", "secret", "-a", "opt2"};

    System.out.println(Arrays.toString(filterOptionAndValue("-k", args)));
}

[-o, opt1, -a, opt2]


0
投票

这是在即将推出的 Java 24 中使用

windowFixed
收集器的解决方案:

String[] args = {
        "-o", "anOption",
        "-k", "aSecretKeyWhoseValueWeShouldNotLog",
        "-a", "anotherOption"
};

String[] filtered = Arrays.stream(args)
        .gather(Gatherers.windowFixed(2))
        .filter(w -> !"-k".equals(w.getFirst()))
        .flatMap(Collection::stream)
        .toArray(String[]::new);

这会将值转换为成对的二元素列表的

Stream<List<String>>
。 它删除初始值为“-k”的对。 最后它会展平这些对并将它们转换回列表。

© www.soinside.com 2019 - 2024. All rights reserved.