Кофе-брейк #176. Сходства и различия между Array и ArrayList. Как написать эффективный метод equals()

Статья из группы Random

Сходства и различия между Array и ArrayList

Источник: Medium Содержание этой статьи посвящено пониманию концепций массива (Array) и ArrayList, а также различий между ними. Кофе-брейк #176. Сходства и различия между Array и ArrayList. Как написать эффективный метод equals() - 1

Массив Java

Массив (Array) — это структура данных, которая позволяет хранить упорядоченную последовательность значений одного типа. Например, вы можете создать массив символов, чисел и так далее. Это применимо для всех примитивных типов и даже для таких объектов, как String. После создания массива мы не можем изменить его размер. Вот общий пример объявления переменной ссылки на массив и выделения массива:

dataType[] arrayName = new dataType[numElements];
Если мы пытаемся добавить больше, чем размер массива, то получаем исключение ArrayIndexOutOfBoundsException.

Объявление массива

Для объявления массива используются символы [ ] после типа данных. Они указывают, что переменная является ссылкой на массив. Ссылочная переменная массива может ссылаться на массивы различных размеров. Ключевое слово new создает место в памяти для хранения массива с определенным количеством элементов. Ссылочная переменная массива назначается для ссылки на этот вновь выделенный массив. В следующем примере объявляется переменная ссылки на массив gameScores, выделяется массив из четырех целых чисел и назначается gameScores для ссылки на выделенный массив.

int[] gameScores = new int[4];
Элементы массива автоматически инициализируются значениями по умолчанию при использовании ключевого слова new для инициализации ссылки на массив. Значение по умолчанию для элементов целочисленных (integer) типов данных и типов данных с плавающей запятой равно нулю, а значение по умолчанию для логических элементов равно false. Вы также можете объявить ссылочную переменную массива, не выделяя сразу массив, а затем назначить переменную с выделенным массивом.

int[] gameScores;

gameScores = new int[4];

Инициализация массива со значениями, отличными от значений по умолчанию

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

int [] myArray = { 5 , 7 , 11 };
В приведенном выше примере создается массив из трех целочисленных элементов со значениями 5, 7 и 11. Такая инициализация массива не требует использования ключевого слова new, поскольку размер массива автоматически устанавливается равным количеству элементов в фигурных скобках. Для больших массивов инициализацию можно выполнить, сначала определив массив, а затем используя цикл для назначения элементов массива. Доступ к элементам массива можно получить, используя их индексы, начинающиеся с нуля.

Int[ ] intArray = new int [ ] {2};
intArray [0] = 1;
intArray [1] = 2;

ArrayList

ArrayList — это упорядоченный список элементов ссылочного типа с изменяемым размером. Также это класс из пакета java.util, принадлежащий Java Collection Framework. ArrayList предоставляет нам динамические массивы и автоматически обрабатывает изменение их размера. По мере добавления элементов в список ArrayList объем его памяти автоматически увеличивается. Использовать ArrayList можно с помощью оператора import java.util.ArrayList;. Также мы можем создать экземпляр ArrayList, используя следующий оператор:

ArrayList<Type> arrayList = new ArrayList<Type>();
Размер списка ArrayList может увеличиться, чтобы поддерживать размещение нужных элементов. ArrayList не поддерживает примитивные типы, такие как int, а поддерживает ссылочные типы, такие как Integer. Распространенной ошибкой среди новичков является объявление ArrayList примитивного типа, такого как int, как в ArrayList<int> myVals. Это приводит к ошибке компиляции: “unexpected type, found : int, required: reference”. Пример: Создадим объект ArrayList с именем cars, в котором будут храниться строки:

import java.util.ArrayList; 

ArrayList<String> cars = new ArrayList<String>();
Для добавления элементов в ArrayList используется метод add(). Чтобы получить доступ к элементу ArrayList, используется метод get().

cars.add("Tesla");
cars.add("BMW");
cars.add("Kia");
cars.get(0);
Разница между встроенным массивом и массивом ArrayList в Java заключается в том, что в первом случае размер массива нельзя изменить (если вы хотите добавить или удалить элементы в/из массива, вам нужно создать новый). Тогда как в ArrayList элементы могут быть добавлены и удалены когда угодно.

Сходства между массивом и ArrayList

  • Array и ArrayList используются для хранения элементов.
  • Array и ArrayList могут хранить нулевые значения.
  • Оба процесса происходят в постоянном времени.
  • Они могут иметь повторяющиеся значения.
  • Array и ArrayList не гарантируют наличие упорядоченных элементов.

Ключевые различия между Array и ArrayList

Основное различие между массивом (Array) и ArrayList заключается в статической природе массива и динамической природе ArrayList. После создания вы не можете изменить размер массива, тогда как ArrayList может изменить свой размер по мере необходимости. Еще одно важное отличие заключается в том, что массив — это базовая функциональность, предоставляемая Java. С другой стороны, ArrayList является частью структуры коллекций в Java. Мы можем получить доступ к элементам массива, используя квадратную скобку, в которой мы можем указать индекс. В то время как для доступа к элементам ArrayList и их изменению существует набор методов. Несмотря на то, что они разные, оба они, тем не менее, сопоставимы по другим параметрам. Обе эти структуры данных в Java основаны на индексах и позволяют хранить объекты. Кроме того, они допускают нулевые значения и дубликаты. Если вы заранее знаете размер объектов, то лучше использовать массив. Но если вы не уверены в размере, то вместо этого следует использовать ArrayList.

Как написать эффективный метод equals()

Источник: Medium Эта публикация поможет вам лучше узнать о применении метода equals() при работе с кодом Java. Если говорить о методе equals() по умолчанию и без какой-либо реализации, то он во многом похож на операцию ==. То есть, этот метод сравнивает объекты. Например, equals() сравнивает две строки и возвращает true, если строки равны, и false, если нет. Учтите, что операция == не рекомендуется для сравнения объектов в Java. Причина в том, что при сравнении объектов == вернет true только если ссылки указывают на один и тот же объект. Самый простой способ избежать проблем: не переопределять метод equals, в этом случае каждый экземпляр класса равен только самому себе. Переопределять equals нужно лишь тогда, когда у класса есть понятие логического равенства, которое отличается от простой идентичности объекта, а суперкласс еще не переопределил равенство. Таким образом, при использовании метода equals() нужно выяснить, являются ли ссылки на объекты логически эквивалентными, и не ссылаются ли они на один и тот же объект.

Свойства метода equals

Каждый метод equals реализует отношение эквивалентности. Он обладает такими свойствами:
  • Рефлексивный (Reflexive): для любого ненулевого ссылочного значения x функция x.equals(x) должна возвращать true.

  • Симметричный (Symmetric): для любых ненулевых ссылочных значений x и y функция x.equals(y) должна возвращать значение true лишь тогда, когда y.equals(x) возвращает значение true.

  • Переходный (Transitive): Для любых ненулевых ссылочных значений x, y, z, если x.equals(y) возвращает true, и y.equals(z) возвращает true, то x.equals(z) также должен возвращать true.

  • Последовательный (Consistent): для любых ненулевых ссылочных значений x и y многократные вызовы x.equals(y) должны постоянно возвращать true или последовательно возвращать false.

  • Ненулевой (Non-nullity): Для любого ненулевого ссылочного значения x функция x.equals(null) должна возвращать false.

Давайте более подробно рассмотрим каждое свойство:

Рефлексивность:

Объект должен быть равен самому себе. Чтобы убедиться в этом, добавьте экземпляр вашего класса в коллекцию. Метод contains вполне может показать, что коллекция не содержит экземпляра, который вы только что добавили.

Симметрия:

Два объекта (они могут быть из разных классов) должны быть равны друг другу.

Последовательность:

Не пишите метод equals, который зависит от ненадежных/изменяющихся ресурсов.

Ненулевой:

Всегда возвращает true, если объект, переданный в equals, имеет значение null.

Подводим итоги:

Вот рецепт качественного метода equals:
  1. Используйте оператор ==, чтобы проверить, является ли аргумент ссылкой на этот объект.

  2. Используйте оператор instanceof, чтобы проверить, имеет ли аргумент правильный тип.

  3. Приведите аргумент к правильному типу.

  4. Для каждого “значимого” поля в классе проверьте, соответствует ли это поле аргумента соответствующему полю этого объекта:

    • Для примитивных полей: чей тип не является float или double, используйте оператор == для сравнений.
    • Для полей ссылок на объекты: рекурсивно вызывайте метод equals; для полей с плавающей запятой используйте статический метод Float.compare(float, float); а для двойных полей используйте Double.compare(double, double).
    • Для полей массива: примените эти рекомендации к каждому элементу. Если каждый элемент в поле массива значим, используйте один из методов Arrays.equals().
    • Некоторые поля ссылок на объекты могут содержать значения null. Чтобы избежать исключения NullPointerException, проверяйте такие поля на равенство с помощью статического метода Objects.equals(Object, Object).
  5. Когда вы закончите писать свой метод equals, задайте себе три вопроса: Является ли он симметричным? Он транзитивный (переходный)? Он последовательный?

И помните, всегда переопределяйте hashCode при переопределении equals.
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ