Тип списка против типа ArrayList в Java

Для пользователей CDT / C / C ++ build также отрегулируйте настройку

в окне> Предпочтения

в разделе C / C ++> Build> Console (!) [/ ​​g2]

(Это время в количестве строк.)

Это также влияет на «CDT Global Build Console».

517
задан nazar_art 2 March 2017 в 06:59
поделиться

6 ответов

У вас есть два варианта: вернуть что-либо или бросить .

int getNumber() 
{
    return 3;
}

int getNumber() 
{
    throw string("Some Var");
}

Если вы бросили , вы должны поймать тип, который вы бросили.

int maint(int argc, char ** argc)
{
     try
     {
           getNumber();
     }
     catch(string std)
     {
          //Your code will execute here if you throw
     }
 }
-121--3429911-

Изменение конструкции метода, скорее всего, необходимо для того, чтобы вырваться из функции, которая предназначена для возврата значения... или вы можете просто вернуть «ошибочное» значение какого-либо рода.

-121--3429921-

Почти всегда Список предпочтительнее ArrayList , поскольку, например, Список может быть преобразован в Список LinkedList без влияния на остальную базу кодов.

Если используется ArrayList вместо List , трудно изменить реализацию ArrayList на LinkedList , поскольку в базе кода используются ArrayList , которые также требуют реструктуризации.

Информацию о списке реализаций можно найти здесь .

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

425
ответ дан 22 November 2019 в 22:24
поделиться

Я бы сказал, что 1 предпочтительнее, если

  • вы не зависите от реализации необязательного поведения * в ArrayList, в этом случае явно используя ArrayList более ясен
  • Вы будете использовать ArrayList в вызове метода, который требует ArrayList, возможно, для необязательного поведения или характеристик производительности

Я предполагаю, что в 99% случаев вы можете обойтись с помощью List, что является предпочтительным .

  • например removeAll или add (null)
1
ответ дан 22 November 2019 в 22:24
поделиться

Каков ваш фактический сценарий использования?

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

Также можно вернуть то, что вызывающий абонент интерпретирует как ошибку (или «ничего не возвращено»).

Каким бы ни было ваше решение, вызывающий абонент должен обработать дело «ничего не возвращено» отдельно, например, поймать исключение или проверить возвращенное значение.

-121--3429922-

Проверьте, не ограничивает ли его максимальное выполнение во время выполнения:

[wally@zf conf]$  ulimit -all
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 16114
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 16114
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Обратите внимание, что размер стека по умолчанию ограничен 10 МиБ. Таким образом, увеличить его до 64 MiB:

[wally@zf conf]$ ulimit -s 64M
-bash: ulimit: 64M: invalid number
[wally@zf conf]$ ulimit -s 65536
[wally@zf conf]$ ulimit -all
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 16114
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 65536
cpu time               (seconds, -t) unlimited
max user processes              (-u) 16114
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
-121--2147966-

Единственный случай, когда я знаю, где (2) может быть лучше, это использование GWT, потому что это уменьшает площадь приложения (не моя идея, но команда google web toolkit говорит так). Но для обычной java, работающей внутри JVM (1), вероятно, всегда лучше.

2
ответ дан 22 November 2019 в 22:24
поделиться

Я думаю, что люди, использующие (2), не знают принцип подстановки Лискова или принцип инверсии зависимостей . Или им действительно нужно использовать ArrayList .

9
ответ дан 22 November 2019 в 22:24
поделиться

(3) Коллекция myCollection = new ArrayList ();

Я обычно использую это. И только , если мне нужны методы List, я буду использовать List. То же самое с ArrayList. Вы всегда можете переключиться на более «узкий» интерфейс, но не можете перейти на более «широкий».

9
ответ дан 22 November 2019 в 22:24
поделиться

Мне интересно, использует ли кто-нибудь (2)?

Да. Но редко по разумной причине (IMO).

И люди обжигаются, потому что используют ArrayList, когда следовало бы использовать List:

  • Утилитарные методы, такие как Collections.singletonList(...) или Arrays.asList(...), не возвращают ArrayList.

  • Методы в List API не гарантируют возврат списка того же типа.

Например, в https://stackoverflow.com/a/1481123/139985 у автора были проблемы с "нарезкой", потому что ArrayList.sublist(...) не возвращает ArrayList ... а он создал свой код так, чтобы использовать ArrayList в качестве типа всех своих переменных списка. В итоге он "решил" проблему, скопировав подсписок в новый ArrayList.

Аргумент, что вам нужно знать, как ведет себя List, в значительной степени решается использованием интерфейса маркера RandomAccess. Да, он немного громоздкий, но альтернатива еще хуже.

Кроме того, как часто ситуация действительно требует использования (1) вместо (2) (т.е. когда (2) не достаточно... не считая "кодирования под интерфейсы" и лучших практик и т.д.)

Часть вопроса "как часто" объективно не имеет ответа.

(и можно пример)

Иногда приложение может потребовать, чтобы вы использовали методы в ArrayList API, которых нет в List API. Например, ensureCapacity(int), trimToSize() или removeRange(int, int). (Причем последний возникнет только в том случае, если вы создали подтип ArrayList, который объявляет метод как public.)

Это единственная разумная причина для кодирования в классе, а не в интерфейсе, IMO.

(Теоретически возможно, что вы получите небольшое улучшение производительности... при определенных обстоятельствах... на некоторых платформах... но если вам действительно не нужны эти последние 0,05%, не стоит этого делать. Это неразумная причина, IMO.)


Вы не можете писать эффективный код, если не знаете, эффективен ли случайный доступ или нет.

Это верное замечание. Однако Java предлагает лучшие способы решения этой проблемы; например,

public <T extends List & RandomAccess> void test(T list) {
    // do stuff
}

Если вы вызовете это со списком, который не реализует RandomAccess, вы получите ошибку компиляции.

Вы также можете тестировать динамически ... используя instanceof ... если статическая типизация слишком неудобна. И вы даже можете написать свой код для использования различных алгоритмов (динамически) в зависимости от того, поддерживает ли список случайный доступ или нет.

Обратите внимание, что ArrayList - не единственный класс списка, реализующий RandomAccess. Другие включают CopyOnWriteList, Stack и Vector.

Я видел, как люди приводили тот же аргумент относительно Serializable (потому что List не реализует его)... но подход выше решает и эту проблему. (В той степени, в какой она вообще решаема с использованием типов времени выполнения. ArrayList не пройдет сериализацию, если какой-либо элемент не сериализуем.)

110
ответ дан 22 November 2019 в 22:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: