我的整数列表在哪里变成Optional <integer>的列表?

时间:2019-04-24 04:00:59

标签: java functional-programming

我正在尝试返回由字符串中的空格分隔的数字的最大值和最小值。这是我到目前为止的内容:

public static String HighAndLow(String numbers) {
    List<Integer> nums = Arrays.asList(numbers.split(" ")).stream()
                                                          .map(s -> Integer.parseInt(s))
                                                          .collect(Collectors.toList());
    int max = nums.stream().reduce((a, b) -> a > b ? a : b);
    int min = nums.stream().reduce((a, b) -> a < b ? a : b);
    return max + " " + min;
    }

但是该代码不会编译,而是返回“

error: incompatible types: Optional<Integer> cannot be converted to int

我不明白...我的代码将整数/字符串转换为可选内容是什么? map会默认执行此操作吗?或者它是我编码方式所独有的?我尝试做另一个映射以在Optional上调用get方法,但这似乎也不起作用。

5 个答案:

答案 0 :(得分:3)

您不需要两次使用reduce操作来获取最小值和最大值。只需在IntSummaryStatistics上使用List<Integer>并从此统计信息中获取MaxMin并摆脱处理Optional

public static String HighAndLow(String numbers) {
    IntSummaryStatistics stats = Arrays.stream(numbers.split(" "))
        .mapToInt(Integer::parseInt)
        .summaryStatistics();
    return stats.getMax() + " " + stats.getMin();
  }

IntSummaryStatistics除了maxmin

之外,还会为您提供更多结果

IntSummaryStatistics{count=10, sum=129, min=2, average=12.900000, max=29}

答案 1 :(得分:2)

reduce返回一个Optional,以便在没有任何值的情况下可以指定任何默认值。因此,要根据您的情况获取int,您需要定义.orElse()值,例如:

public static String highAndLow(String numbers) {
        List<Integer> nums = Arrays.asList(numbers.split(" ")).stream()
                .map(s -> Integer.parseInt(s))
                .collect(Collectors.toList());
        int max = nums.stream().reduce((a, b) -> a > b ? a : b).orElse(0);
        int min = nums.stream().reduce((a, b) -> a < b ? a : b).orElse(0);
        return max + " " + min;
}

答案 2 :(得分:1)

您将获得Optional<Integer>,因为这是reduce(...)的返回类型。它返回Optional,因为列表中没有减小的值。

当然,在您的情况下,不会出现空列表,因为如果numbers为空,则numbers.split(" ")将返回一个包含一个空字符串的数组,而Integer.parseInt(s)将抛出{{ 1}}。

添加filter(...)可以忽略该空值。如果输入为空,则需要确定要让方法返回的内容,例如一个空字符串。

现在您知道列表不为空,只需调用get()即可解开NumberFormatException: For input string: ""

您应该使用max(...)min(...)而不是调用Optional

reduce(...)

更好的是,不要将所有数字都装在public static String highAndLow(String numbers) { List<Integer> nums = Arrays.asList(numbers.split(" ")).stream() .filter(s -> ! s.isEmpty()) .map(Integer::valueOf) .collect(Collectors.toList()); if (nums.isEmpty()) return ""; int max = nums.stream().max(Comparator.naturalOrder()).get(); int min = nums.stream().min(Comparator.naturalOrder()).get(); return max + " " + min; } 对象中。您应该使用Integer代替Stream<Integer>

IntStream

答案 3 :(得分:0)

当对流的元素执行归约运算时,它返回一个Optional描述归约值。因此, reduce操作将包装到Optional 。 这是减少操作内部实现的示例

public final Optional<P_OUT> reduce(){
   boolean foundAny = false;
   T result = null;
   for (T element : this stream) {
      if (!foundAny) {
        foundAny = true;
        result = element;
     }else
       result = accumulator.apply(result, element);
   }
 return foundAny ? Optional.of(result) : Optional.empty();
}

您可以直接使用reduce操作

int max1 = nums.stream().reduce(Integer::max).get();
int min1 = nums.stream().reduce(Integer::min).get();

如果您想通过其他方式获取最小值和最大值,可以在how to find maximum value from a Integer using stream in java 8?问题上看到@Tagir Valeev的答案

答案 4 :(得分:0)

public static String HighAndLow(String numbers) {
    List<Integer> nums = Arrays.asList(numbers.split(" ")).stream().map(s -> Integer.parseInt(s))
            .collect(Collectors.toList());
    int max = nums.stream().reduce((a, b) -> a > b ? a : b).orElse(0);
    int min = nums.stream().reduce((a, b) -> a < b ? a : b).orElse(0);
    return max + " " + min;
}

带有一个参数的reduce()方法返回一个Optional,这是一个用于null安全的Java类,您可以使用orElse并为max和min定义想要的任何值,例如0和0,

希望有帮助