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

Создание эффективного сортировочного разделителя Java 8 из массива

В Java 8 предлагается множество удобных утилит для создания эффективных разделителей из массивов. Однако здесь не существует методов factory для создания Spliterator со компаратором. Очевидно, что разделителям разрешено иметь прилагаемые компараторы; у них есть метод getComparator() и SORTED свойство.

Как авторы библиотеки должны строить SORTED Spliterators?

4b9b3361

Ответ 1

Кажется, что не существует такого Spliterator с порядком, отличным от естественного. Но реализовать это не так сложно. Это может выглядеть так:

class MyArraySpliterator implements Spliterator.OfInt {
    final int[] intArray;
    int pos;
    final int end;
    final Comparator<? super Integer> comp;

    MyArraySpliterator(int[] array, Comparator<? super Integer> c) {
        this(array, 0, array.length, c);
    }
    MyArraySpliterator(int[] array, int s, int e, Comparator<? super Integer> c) {
        intArray=array;
        pos=s;
        end=e;
        comp=c;
    }
    @Override
    public OfInt trySplit() {
        if(end-pos<64) return null;
        int mid=(pos+end)>>>1;
        return new MyArraySpliterator(intArray, pos, pos=mid, comp);
    }
    @Override
    public boolean tryAdvance(IntConsumer action) {
        Objects.requireNonNull(action);
        if(pos<end) {
            action.accept(intArray[pos++]);
            return true;
        }
        return false;
    }
    @Override
    public boolean tryAdvance(Consumer<? super Integer> action) {
        Objects.requireNonNull(action);
        if(pos<end) {
            action.accept(intArray[pos++]);
            return true;
        }
        return false;
    }
    @Override
    public long estimateSize() {
        return end-pos;
    }
    @Override
    public int characteristics() {
        return SIZED|SUBSIZED|SORTED|ORDERED|NONNULL;
    }
    @Override
    public Comparator<? super Integer> getComparator() {
        return comp;
    }
}

Но Java 8 еще не полностью исправлена. Возможно, в финале будет предоставлено JRE-решение.

Ответ 2

Вы можете создать разделитель ORDERED:

  • начиная с коллекции с помощью соответствующего iterator():

    У коллекции есть порядок встреч, если соответствующий Collection.iterator() документирует заказ. Если это так, порядок встреч совпадает с документированным порядком. В противном случае коллекция не имеет порядка встреч.

    Как правило, TreeSet.spliterator#getComparator возвращает Компонента TreeSet, но ArrayList.spliterator#getComparator возвращает null: порядок - путем увеличения индекса.

  • или, если у вас есть массив, используя новые методы удобства, предоставляемые в Arrays вспомогательном классе, например Arrays.spliterator(double[]):

    Разделитель сообщает Spliterator.SIZED, Spliterator.SUBSIZED, Spliterator.ORDERED и Spliterator.IMMUTABLE.

  • или (что делает Arrays.spliterator), явно предоставляя такие характеристики, как: Spliterators.spliterator(array, Spliterator.ORDERED);

Когда сбор не связан с конкретным компаратором (или с массивами), имеет смысл сортировать до "раздробления".