#java #generics #arraylist #collections #linked-list
Вопрос:
Оба LinkedList
и ArrayList
построены на интерфейсе списка, однако LinkedList
для построения списка используется традиционный метод указателя, а ArrayList
для реализации List
функциональности используется массив . Итак, что можно утверждать перед использованием nums, будет ли он использоваться ArrayList
или LinkedList
за экраном?
Как у меня возник этот вопрос?
public int[] smallestRange(List<List<Integer>> nums) {
}
}
Большая часть вопроса Java с кодом Leetcode имеет такой формат ввода. Без предварительного знания того, как были созданы экземпляры num, как кто-то может использовать nums.get(i)
функцию ( list.get(i)
является O(1) в списке ArrayList и O(n) в списке ссылок )
Комментарии:
1. Ни один из них
List
не является интерфейсом, и вы не можете (не должны) предполагать внутреннее представление (конечно, вы могли бы проверить во время выполнения, но не должны). Если вам нужна быстрая реализация, создайте свой собственный ограниченный интерфейс/класс или напишите напрямуюsmallestRange(ArrayList<...> ...)
.2. Это очень веская причина избегать
list.get(int)
и вместо этого использовать итератор.
Ответ №1:
В 99% случаев это будет an ArrayList
, и вы хотите использовать an ArrayList
в своем коде. Они используют меньше памяти, быстрее, и код, использующий преимущества LinkedList
, обычно может быть переписан для использования двух ArrayLists
. Основным недостатком является add()
то, что время от времени он работает в O(n) время.
как кто-то может использовать nums.get(i)
Вы не. Вы пользуетесь тем, что список есть Iterable
, и делаете такие вещи, как для каждого цикла:
for (var i : list) {
...
}
это выполняется за O(n) время для обоих LinkedList
и ArrayList
.
Технически, есть интерфейс под названием RandomAccess
» вы можете проверить, является ли get()
он O(1)». Хотя ты, наверное, этого не хочешь. Используйте итератор.
if (list instanceof RandomAccess) {
list.get(...);
}
Комментарии:
1. Абсолютно правильно: в принципе нет причин активно использовать
LinkedList
, даже Джошуа Блох, который написал это , не использует его. И большую часть времени вам должно быть все равно, какая конкретнаяList
реализация используется. Единственное, чего мне не хватает, — это объяснения, когда проверкаRandomAccess
может оказаться полезной, если вообще когда-либо будет.2. @JoachimSauer В вашем собственном приложении это самая простая стратегия, которую можно просто избежать
LinkedList
. Но сам код JDK использует проверки дляRandomAccess
переключения алгоритмов , что разумно, поскольку он не может предсказать, будет ли использоваться код приложенияLinkedList
или нет. ИLinkedList
часто всплывает в вопросах SO, что говорит о том, что, возможно, многие программы все еще используют его. Я боюсь, что есть учителя, которые дают плохие советы начинающим…3. Что касается «алгоритмов переключения», очевидный случай заключается в том, какую реализацию сортировки использовать. Я думаю, что он сортирует на месте для RandomAccess, но копирует неслучайные списки в список массивов, сортирует на месте, а затем заменяет элементы.
4. @DavidEhrmann реализация по умолчанию
sort
всегда создает копию. Причина в том, что он поддерживаетсяArrays.sort(…)
, для чего в любом случае требуется массив. ТолькоArrayList
иVector
переопределяют его, чтобы передавать свои внутренние массивы напрямуюArrays.sort(…)
. Но в основном все остальные операции (reverse
,shuffle
,fill
,,copy
,rotate
,replaceAll
,indexOfSubList
,binarySearch
) имеют такой переключатель.
Ответ №2:
Вы не можете напрямую указать, что является реализацией интерфейса списка по умолчанию. Интерфейс-это всего лишь спецификация, и у вас есть несколько реализаций интерфейса списка, как вы упомянули на изображении.
Каждая реализация просто переопределит метод, упомянутый в интерфейсе списка, но их логика будет отличаться в зависимости от структуры данных.
Теперь это полностью зависит от вас, какую реализацию вы хотите, исходя из ваших требований. Независимо от того, ограничены ли у вас пространство или время. Но у обоих будет тот же метод, что и в интерфейсе.
В соответствии с платформой проблем кодирования я думаю, что они указывают код, из которого они вызвали этот метод. Вы можете проверить там, но если это не указано, то, скорее всего, они выберут ArrayList — для ограничения по времени. И я думаю, что пользователь не должен беспокоиться о реализации, которую он выбрал. Как я уже говорил, пользователь должен знать, каковы его требования, а затем только выбирать реализации.
Ответ №3:
Это может быть любой из них:
List<List<Integer>> list1 = new ArrayList<>();
List<List<Integer>> list2 = new LinkedList<>();
int[] x = smallestRange(list1); //works
int[] y = smallestRange(list2); //also works
Вам нужно сделать так, чтобы ваш код мог работать с обоими типами
Комментарии:
1. Либо один из них, либо большое количество других возможностей, включая сторонний код или ваш собственный.