Где мой список целых чисел превращается в список необязательных <Integer>? - PullRequest
0 голосов
/ 24 апреля 2019

Я пытаюсь вернуть максимальное и минимальное значение чисел, разделенных пробелами в строке.Вот что у меня есть:

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

Я не понимаю ... Что в моем коде конвертируетсяцелые числа / строки в Optional? Карта делает это по умолчанию, или это уникально для способа, которым я ее кодирую? Я попытался создать другую карту для вызова метода get в Optional, но это тоже не сработало.

Ответы [ 5 ]

3 голосов
/ 24 апреля 2019

Вам не нужно использовать reduce операцию дважды для получения минимума и максимума.Просто используйте IntSummaryStatistics на List<Integer> и получите Max и Min из этой статистики и избавьтесь от обработки Optional

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

IntSummaryStatistics дает вам больше результатов, чем maxи min

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

2 голосов
/ 24 апреля 2019

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;
}
1 голос
/ 24 апреля 2019

Вы получаете Optional<Integer>, потому что это тип возврата reduce(...).Он возвращает Optional, потому что нет никакого уменьшенного значения из пустого списка.

Конечно, в вашем случае пустой список не может произойти, потому что еслиnumbers пусто, numbers.split(" ") вернет массив из одной пустой строки, а Integer.parseInt(s) выдаст NumberFormatException: For input string: "".

Добавьте filter(...), чтобы игнорировать это пустое значение.Вам нужно решить, что вы хотите, чтобы ваш метод возвращал, если вход пустой, например, пустая строка.

Теперь, когда вы знаете, что список не пуст, вы можете просто развернуть Optional, вызвав get().

Вместо вызова reduce(...) следует использовать max(...) и min(...):

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:

public static String highAndLow(String numbers) {
    int[] nums = Arrays.asList(numbers.split(" ")).stream()
            .filter(s -> ! s.isEmpty())
            .mapToInt(Integer::parseInt)
            .toArray();
    if (nums.length == 0)
        return "";
    int max = IntStream.of(nums).max().getAsInt();
    int min = Arrays.stream(nums).min().getAsInt(); // Arrays.stream is alternate to IntStream.of
    return max + " " + min;
}
0 голосов
/ 24 апреля 2019
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;
}

Метод redu () с одним параметром возвращает Optional, который является Java-классом для нулевой безопасности, вы можете использовать orElse и определять любое значение, которое вы хотите для max и min, например 0 и 0,

Надеюсь, это поможет

0 голосов
/ 24 апреля 2019

, когда он выполняет операцию сокращения над элементами потока, он возвращает Необязательный параметр, описывающий приведенное значение. Так что операция понижения будет перенесена в опциональную . Вот пример внутренней реализации операции сокращения

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();
}

В вашем случае вы можете напрямую использовать операцию уменьшения

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

Если вам нужны другие способы получения минимальных и максимальных значений, вы можете увидеть ответ @Tagir Valeev на как найти максимальное значение из целочисленного значения с использованием потока в java 8? вопрос

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...