Почему массивы нельзя использовать в качестве ключей в Map и чем они отличаются от примитивных типов
Что проверяют
Понимаете ли вы контракт hashCode и equals и знаете ли, что массив в Java это объект, у которого оба метода достались от Object. Попутно проверяют, отличаете ли вы примитив от обёртки.
Как отвечать
Первое: запрета нет. Map<int[], String> компилируется, put отрабатывает, ошибка вылезает молча и в рантайме.
Map<int[], String> m = new HashMap<>();
int[] key = {1, 2, 3};
m.put(key, "a");
m.get(new int[]{1, 2, 3}); // null
m.get(key); // "a"Причина в том, что массив не переопределяет hashCode и equals: хеш берётся от идентичности объекта, равенство сводится к сравнению ссылок. Два массива с одинаковым содержимым для мапы разные ключи, и достать значение можно только по той самой ссылке, которую клали.
Сравнение с примитивами тут не совсем корректно: примитив ключом быть не может вовсе, при вызове put происходит автоупаковка в Integer или Long. У обёрток оба метода переопределены по значению, а сами объекты неизменяемы, поэтому ключ ведёт себя предсказуемо. То же с String и с record, где методы генерирует компилятор.
Чем заменить массив: List<Integer> (у списков равенство по содержимому), строка или record, собственная обёртка с Arrays.hashCode и Arrays.equals внутри, для байтов удобен ByteBuffer.wrap. Если нужен упорядоченный ключ, подойдёт TreeMap с компаратором Arrays::compare, ему хеш не требуется вообще.
Где спотыкаются
Говорят, что такой код не скомпилируется. Компилируется, и в этом вся неприятность: мапа тихо копит дубликаты, а get возвращает null, причём падает это далеко от места ошибки.
Предлагают переопределить hashCode у массива. У массива переопределить ничего нельзя, его класс создаёт JVM. Arrays.hashCode считает хеш по содержимому, но сам по себе на поведение мапы не влияет: он должен оказаться внутри класса-обёртки рядом с equals.
Забывают про изменяемость. Ключ, чей хеш зависит от изменяемого состояния, после правки теряется в своей корзине: мапа ищет его в другой. Поэтому и List в роли ключа кладут только неизменяемым.