1

As you know, dropWhile for streams was introduced in java 9. But if the target of the project is java 8, you can't use it.

Example code:

public static String getParameterValueOrDefault(String[] args, String paramName, String defaultVal) {
    return Arrays.stream(args).sequential().dropWhile(arg->!arg.equals("/"+paramName) && !arg.equals("-"+paramName)).skip(1).findFirst().orElseGet(()->defaultVal);
}

What I want is an equivalent lambda expression written in java 8.

PatoOta
  • 11
  • 3
  • 1
    There’s the `arg ->` missing in `dropWhile`. Further, there’s no advantage in using `orElseGet(() -> defaultVal)` over the simpler and more efficient `orElse(defaultVal)` – Holger Jan 17 '23 at 07:45
  • Correct, I will edit to add arg-> – PatoOta Jan 26 '23 at 16:18

2 Answers2

2

You can use

public static String getParameterValueOrDefault(
                     String[] args, String paramName, String defaultVal) {

    int ix = IntStream.range(0, args.length)
        .filter(i -> args[i].matches("[/-]" + Pattern.quote(paramName)))
        .map(i -> i + 1)
        .findFirst().orElse(args.length);
    return ix < args.length? args[ix]: defaultVal;
}

The matches approach is for convenience, if you prefer compact code. If you want an efficient check, you may instead use:

public static String getParameterValueOrDefault(
                     String[] args, String paramName, String defaultVal) {

    int ix = IntStream.range(0, args.length)
        .filter(i -> {
            String arg = args[i];
            return arg.length() == paramName.length() + 1 && arg.endsWith(paramName)
                && (arg.charAt(0) == '-' || arg.charAt(0) == '/');
        })
        .map(i -> i + 1)
        .findFirst().orElse(args.length);
    return ix < args.length? args[ix]: defaultVal;
}
Holger
  • 285,553
  • 42
  • 434
  • 765
  • IMHO my aswer is better (or tell me I am wrong) because it is rewriten only the dropWhile, so the rest of the expression does not change. – PatoOta Jan 26 '23 at 16:24
  • 1
    @PatoOta your answer is a textbook example of how not to use streams 1.) modifying state outside the stream and relying on side effects 2.) abusing `peek`. My answer does not require `sequential()` (nor assumptions about how a sequential stream is implemented). – Holger Jan 26 '23 at 16:50
0

I found this way:

public static String getParameterValueOrDefault(String[] args, String paramName, String defaultVal) {
    MutableBoolean foundParam = new MutableBoolean(false);
    return Arrays.stream(args).sequential().peek(arg->foundParam.value = foundParam.value || arg.equals("/"+paramName) || arg.equals("-"+paramName)).filter(arg->foundParam.value).skip(1).findFirst().orElseGet(()->defaultVal);
}

Where MutableBoolean is:

private static class MutableBoolean {
    boolean value;
    public MutableBoolean(boolean value) {
        this.value = value;
    }
}
PatoOta
  • 11
  • 3
  • This is my first question, and my first answer. An I am not an English speaker. Sorry for any mistake abot rules and writtings. – PatoOta Jan 16 '23 at 13:31