Подтвердить что ты не робот

Могу ли я проверить, содержит ли поток Java 8 не менее n элементов

У меня есть поток Java 8, из которого я хочу (равномерно) случайным образом выбрать элемент. Поток может содержать от нуля до десятков тысяч элементов.

Я реализовал алгоритм, который выбирает один, используя шаблон, похожий на MapReduce, но для очень маленьких потоков, вероятно, было бы более эффективно собирать элементы в список и возвращать один со случайным индексом. Тем не менее, я должен их сосчитать. У потоков есть метод count(), но это все их число, я действительно не заинтересован в фактическом счете, все, о чем я забочусь, заключается в том, содержит ли он больше, чем определенное число. Кто-нибудь знает, существует ли такой метод? Я не могу найти его, но может быть что-то, что я упускаю из виду, или какой-нибудь умный трюк, чтобы найти его в любом случае.

P.S.: Я знаю, что иногда не нужно оптимизировать код; но я хотел бы попробовать это, тем не менее, только для опыта. Я студент.

P.P.S.: Я скопировал свой алгоритм здесь, в случае, если кто-то заинтересован (или хочет искать ошибки, я еще не тестировал его;)

stream
    .parallel()
    .map(t -> new Pair<T, Integer>(t, 1))
    .reduce((Pair<T, Integer> t, Pair<T, Integer> u) -> {
        if (rand.nextDouble() <= (t.getValue1() / (double) (t.getValue1() + u.getValue1()))) {
            return new Pair<>(t.getValue0(), t.getValue1() + u.getValue1());
        } else {
            return new Pair<>(u.getValue0(), t.getValue1() + u.getValue1());
        }
    })
    .map(t -> t.getValue0());

(пары из org.javatuples, теперь, когда Java поддерживает функциональные программируемые интерфейсы, отсутствие кортежей становится немного болезненным).

4b9b3361

Ответ 1

Ваш код не возвращает элемент из равномерного распределения. Это зависит от порядка, который поток предоставляет элементы для уменьшения метода. В общем случае вы не можете считать, что заказ не будет особенным. Решение вашей задачи: если у вас достаточно памяти, можно записать RandomComparator (который сохраняет предыдущие результаты в Map), сортировать поток с помощью этого компаратора и получать первый элемент (не использовать findAny). Если поток слишком велик, его можно попробовать с помощью RandomFilter.

btw, если в вашем потоке есть флаг SIZED, задача тривиальна. Просто получите размер, создайте случайный индекс и сделайте spip:)

Ответ 2

Я предлагаю попробовать получить эту информацию из источника данных для потока. Откуда вы берете данные для потока? Если источник (например, некоторая коллекция) может предоставить вам количество элементов, которые вы установили. Если какая-то функция производителя проверяет, что она делает, и можно ли оценить размер аванса.

В момент ввода "потока" я обычно начинаю думать о "рецепте" того, что я хочу делать с этими данными, а не фактическими данными. Я думаю, что близко к тому, как создаются потоки (что говорит, почему они не предоставляют способ подсчета элементов).

С уважением, Dido

Ответ 3

Я полагаю, что на первоначальный вопрос уже был дан ответ, но я продолжаю приземляться здесь, ища "поток java, по крайней мере, n элементов" или аналогичный, так что, возможно, это все еще будет полезно для некоторых.

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

class Scratch
{
    public static void main(String[] args)
    {
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        List<Integer> list2 = Arrays.asList(1, 2, 3, 4);

        System.out.println(streamContainsAtLeastNElements(list1.stream(), 4));
        // --> false
        System.out.println(streamContainsAtLeastNElements(list2.stream(), 4));
        // --> true
    }

    public static boolean streamContainsAtLeastNElements(Stream<?> stream, long minCount)
    {
        return stream.limit(minCount).count() == minCount;
    }
}

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