Как применить сокращение Stream (число) к IntStream и изменить тип возвращаемого значения на «int» - PullRequest
0 голосов
/ 11 февраля 2019

Этот код не будет компилироваться:

public int trailingZeroes(int n) {
    return IntStream.rangeClosed(1,n)
            .filter(e -> (e  % 5) == 0)
            .count();
}

Я заметил эту разницу в типах возврата IntStream методов:

int sum() против long count()

Пытаясь вернуть тип int из описанной выше операции подсчета,

  • Я уже понимаю, почему count() возвращает длинную, но почему sum() верните более узкий тип возврата, чем count()?

  • Каков наилучший способ добиться того, что я пытаюсь сделать с помощью моего
    trailingZeroes метода?

Ответы [ 4 ]

0 голосов
/ 11 февраля 2019

Я уже понимаю, почему count () возвращает long, но почему sum () возвращает более узкий тип возврата, чем count ()?

sum() возвращает сумму элементовв потоке, поэтому возвращаемый тип соответствует типу потока.LongStream.sum() возвращает long.

count() не имеет прямого отношения к типу объектов, поступающих из потока, и соответствует остальным Stream классам, которые они выбрали long, тип, который представляет наибольший размер,Метод count() фактически определяется на уровне интерфейса Stream, который затем расширяется на BaseStream, а затем на IntStream, поэтому контракт сигнатуры метода должен быть сохранен.(В идеале count() должен был бы вернуть unsigned, но Java не поддерживает unsigned.)

Как лучше всего добиться того, что я пытаюсь сделать в моих trailingZeroesметод?

Не ясно, чего вы пытаетесь достичь.Но я не вижу ничего особенно плохого в этом.

Если вы хотите, чтобы он возвратил int, приведите значение перед возвратом.Я предполагаю, что вы знаете, что результат всегда будет безопасно помещаться в int (результат всегда будет меньше, чем n, что является int), если вы не хотите изменить тип возвращаемого значения вашего метода на long,

С другой стороны, не могу понять, что должен делать этот метод.Вы могли бы только что сделать:

public int trailingZeroes(int n) {
  return n / 5;
}

Если вы ищете математический способ определить, сколько трейлингов 0 у вас есть в целом числе, оно будет другим.У вас уже есть предложенный ответ, поэтому я позволю себе предложить рекурсивное решение для удовольствия:

public int trailingZeroes(int n) {
   return (n % 10 != 0) 
        ? 0 
        : 1 + trailingZeroes(n / 10);
}
0 голосов
/ 11 февраля 2019

Метод sum возвращает int, потому что сумма двух целых чисел равна целому.

Javadoc для count говорит, что он эквивалентен mapToLong(e -> 1L).sum().Вы можете использовать это, чтобы сделать свой собственный подсчет, который возвращает int, например:

return IntStream.rangeClosed(1,n)
        .filter(e -> (e  % 5) == 0)
        .map(e -> 1)
        .sum();

Или, поскольку вы на самом деле знаете, что ваш ответ в любом случае поместится в int, просто приведите его:

return (int) IntStream.rangeClosed(1,n)
        .filter(e -> (e  % 5) == 0)
        .count();
0 голосов
/ 11 февраля 2019

count () возвращает long, но почему sum () возвращает более узкий тип возврата, чем count ()?

Из Javadocs, IntStream.countслучается, что это особый случай сокращения

return mapToLong(e -> 1L).sum();

, поэтому он возвращает long.Далее IntStream.sum снова является специальным сокращением, которое внутренне использует Integer.sum

return reduce(0, Integer::sum) // signature of sum being 'int sum(int a, int b)'

, поэтому возвращает int.

Как лучше всего добиться того, что я пытаюсь сделать с помощью метода trailingZeroes?

Небольшая оптимизация по сравнению с другими решениями, вы можете использовать просто map как:

public int trailingZeroes(int n) {
    return IntStream.rangeClosed(1, n)
        .map(e -> (e % 5) == 0 ? 1 : 0)
        .sum();
}

Исходя из имени метода, вы должны искать в своей реализации:

public int trailingZeroes(int n) {
    int count = 0;
    while (n % 10 == 0) {
        count++;
        n = n / 10;
    }
    return count;
}

, который при представлении в синтаксисе Java-9 должен выглядеть следующим образом:

public int trailingZeroes(int n) {
    return (int) IntStream.iterate(n, i -> i % 10 == 0, i -> i / 10).count();
}
0 голосов
/ 11 февраля 2019

sum() возвращает сумму элементов в этом потоке, и поскольку вы используете IntStream, sum() возвращает тип int.Примечание: sum() метод для LongStream вернет long тип.

Чтобы получить int, вы можете просто использовать приведение:

return (int)IntStream.rangeClosed(1,n)
            .filter(e -> (e  % 5) == 0)
            .count();
...