Как понять этот метод Java 8 Stream collect ()?

12

Я пытался преобразовать массив int в List, и я выбрал незнакомый путь использования Java 8 Stream и придумал

Arrays.stream(arr).boxed().collect(Collectors.toList());

Я до сих пор с трудом полностью понимаю эту строку, в основном,

  1. Почему Collectors.toList()в этом случае возвращается ArrayList<Integer>реализующий Listинтерфейс? Почему нет LinkedList<Integer>или какой-либо другой универсальный класс, соответствующий Listинтерфейсу? Я ничего не могу найти по этому поводу, за исключением краткого упоминания ArrayList здесь , в разделе API Notes.

  2. Что означает левая панель ? Очевидно, это общий тип возврата ( в моем коде здесь). И я думаю, что это аргумент общего типа метода, но как они указаны? Я заглянул в интерфейсный документ Collector и не смог его поглотить.введите описание изображения здесь Stream.collect()RArrayList<Integer><R, A>

user3207158
источник
2
1. Это действительно использует фактический список под капотом, очевидно. Но было бы неразумно для API раскрывать фактический базовый тип List. С тех пор они никогда не смогут изменить реализацию в будущем. В целом, часто хорошей идеей является предоставление только интерфейсов, а не фактического базового типа. 2. Rявляется универсальным типом результирующего типа. Aуниверсальный тип промежуточного типа накопления коллектора. Это деталь реализации того, как работает коллектор. Он разделяет и захватывает, также для параллельной обработки, сначала собирает в промежуточные типы.
Забузард
10
Вы почти никогда не хотите LinkedList. Джош Блох пишет в твиттере : «Я написал это и никогда не использую».
Энди Тернер
4
«Почему Collectors.toList()в этом случае возвращает ArrayList<Integer>» Может не вернуть ArrayList. ListРеализация не определена , так что вы не можете полагаться на то , что реализация возвращается. Как сказано в javadoc : «Нет никаких гарантий относительно типа , изменчивости, сериализуемости или безопасности потоков возвращаемого List»;
Андреас
3
и toList()не возвращает ArrayListили List- он возвращает a Collector, что в конечном итоге создаст и вернет a List- также документация гласит: «... Нет никаких гарантий относительно типа , изменчивости, сериализуемости или безопасности потока возвращаемого списка; если требуется больший контроль над возвращенным списком, используйте toCollection (Supplier) .... "
user85421-Banned
3
Я настоятельно рекомендую пакетную документацию
Хольгер

Ответы:

18
  1. Это реализация по умолчанию. ArrayListиспользуется, потому что это лучше в большинстве случаев, но если это не подходит для вас, вы всегда можете определить свой собственный коллектор и предоставить фабрику для Collectionвашего желания:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. Да, Aи Rявляются общими параметрами этого метода, Rэто тип возвращаемого значения, Tявляется типом ввода и Aявляется промежуточным типом, который появляется во всем процессе сбора элементов (может быть невидимым и не относится к этой функции). Начало CollectorJavadoc «S определяет те типы (они совместимы по всему документу):

    T - тип элементов ввода для операции сокращения
    A - изменяемый тип накопления операции сокращения (часто скрытый как деталь реализации)
    R - тип результата операции сокращения

Андроник
источник
Да я вижу. Я думаю, что я должен придерживаться List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());и вызывать только методы, объявленные в интерфейсе List на myList. В противном случае я бы подверг себя риску, если Oracle решит изменить реализацию по умолчанию в Java8u1024 или 15?
user3207158
2
@ user3207158 метод возвращает a List, поэтому, независимо от используемой реализации, поведение будет одинаковым. Вряд ли интерфейс будет изменен в более новых версиях Java.
Андроник
1
  1. Почему Collectors.toList () в этом случае возвращает ArrayList, реализующий интерфейс List?

Как предполагает определение метода, он возвращает реализацию Collector с поставщиком коллекционера as ArrayList. Следовательно, из определения метода ниже очень ясно, что Collectors.toListвсегда возвращается ArrayList collector ( While it's arguable why toList not toArrayList word is used in method name).

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. Что делает левую панель <R, A> R collect(Collector<? super T, A, R> collector)средств

Если вы ссылаетесь на комментарии к документации, в ней точно упоминаются следующие общие типы:

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);
Виная Праджапати
источник
Спасибо, сэр. Где вы взяли исходный код Collectors.toList()(первый фрагмент)? Это openjdk?
user3207158
1
Нет! Я скачал исходный код в моем intelli J
Vinay