В чем отличие объявление переменных HashMap от Map?
В чем отличие если мы объявим переменную так:
HashMap<Type, Type> lala = new HashMap<>();
Или так:
Map<Type, Type> lala = new HashMap<>();
В чем практическое отличие, почему в некоторых случаях объявляют как в первом случае, а в других как во втором. Так же касается и ArrayList
Ответы (2 шт):
Отличие в том, что во втором случае lala объявляется как ссылка на интерфейс Map, а в первом -- на конкретную реализацию HashMap этого интерфейса. Соответственно, во втором случае можно легко переприсвоить переменной lala какую-нибудь другую реализацию:
Map<String, Integer> lala = new HashMap<>();
lala = new TreeMap<>(lala); // получить отсортированную мапу
Особой разницы в данном случае между двумя указанными способами нет, так как HashMap не имеет каких-то своих особых методов, не объявленных в интерфейсе, в отличие от реализации TreeMap (для которой, впрочем существуют расширенные интерфейсы SortedMap / NavigableMap).
Первый способ позволяет воспользоваться полным функционалом, реализованным в классе, без дополнительного приведения типа.
Второй помогает уменьшить связанность кода и поэтому может считаться более предпочтительным, так как в таком случае в коде создаётся зависимость от абстракции (интерфейса), а не конкретной реализации.
То же относится и к связке List / ArrayList. Например, если нужно пользоваться методами доступа к элементам списка по индексу get(int index) / set(int index, E elem), то придётся использовать конкретную реализацию:
ArrayList<Foo> arrList = new ArrayList<>();
arrList.add(new Foo(1));
arrList.set(0, new Foo(2));
Но в основном, при создании списков другими способами: Arrays.asList, List.of, и др. гораздо удобнее пользоваться общим интерфейсом, не вдаваясь в детали реализации:
List<Integer> nums = Arrays.asList(1, 2, 3); // java.util.Arrays$ArrayList
List<Integer> copies = Collections.nCopies(5, 10); // java.util.Collections$CopiesList
List<String> strs = List.of("a", "b"); // java.util.ImmutableCollections$List12
тут надо понимание интерфейсов и коллекций.
если в двух словах Map, как и List интерфейсы, которые реализуют коллекции типа HashMap и ArrayList и т.д. а также реализуют все методы интерфейса.
Проще обращаться именно к интерфейсу, или так скажем, к более общему объекту/классу/сущности, нежели к ее конкретной реализации
public void someMethod(List<String> list) {
}
В этот метод можем передавать ArrayList, LinkedList и любую другую коллекцию, реализующую List.
так же переприсвоить другую реализацию ссылки
List<Integer> list = new LinkedList<>();
list = new ArrayList<>();
по этому принципу работает ключевое слово var
var list = new ArrayList<>();