Java for Beginner
675 subscribers
559 photos
156 videos
12 files
856 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Pair

В программировании часто возникает необходимость работать с парами значений, например, для хранения координат точки на плоскости, ключей и значений в словаре, или даже результатов вычислений. В Java нет встроенного класса Pair в стандартной библиотеке, однако многие библиотеки, такие как Apache Commons и JavaFX, предоставляют свою реализацию этого класса.

Класс Pair используется для хранения двух связанных объектов, которые могут быть разного типа. Эти объекты часто называют first и second (или key и value), что делает класс удобным для хранения связок данных, которые логически объединены. Например, Pair может использоваться для хранения координат точки (x, y), имени и фамилии, ключа и значения в словаре, и т.д.

Простейшая реализация класса Pair может выглядеть следующим образом:
public class Pair<K, V> {
private final K key;
private final V value;

public Pair(K key, V value) {
this.key = key;
this.value = value;
}

public K getKey() {
return key;
}

public V getValue() {
return value;
}

@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}


Эта реализация использует дженерики (K и V), что позволяет создавать пары объектов любого типа. Например, можно создать пару с типами String и Integer, что может быть полезно для хранения данных типа "имя-возраст":
Pair<String, Integer> person = new Pair<>("John", 30);
System.out.println(person.getKey()); // Выводит: John
System.out.println(person.getValue()); // Выводит: 30


Особенности использования Pair

Класс Pair обладает несколькими особенностями, которые делают его удобным инструментом в разработке:
Простота и универсальность: Pair позволяет легко объединять два объекта любого типа в одну сущность, не требуя создания отдельных классов для каждой комбинации типов.
Иммутабельность (неизменяемость): В большинстве реализаций класса
Pair значения полей key и value устанавливаются только в момент создания объекта и не могут быть изменены впоследствии. Это обеспечивает безопасность данных и предотвращает их случайное изменение.
Поддержка дженериков: Возможность использовать дженерики позволяет создавать пары любых типов, что делает класс
Pair универсальным инструментом для хранения данных.
Совместимость с различными библиотеками: Многие популярные библиотеки, такие как Apache Commons и JavaFX, содержат свои реализации класса
Pair, что облегчает интеграцию с другими инструментами и фреймворками.

Внутреннее устройство Pair

Внутреннее устройство класса Pair на примере его реализации в библиотеке Apache Commons. Эта библиотека предоставляет готовый класс Pair, который можно использовать в своем проекте, добавив зависимость в ваш проект.

Пример реализации Pair из Apache Commons:
public class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {
private static final long serialVersionUID = 1L;
private final L left;
private final R right;

public Pair(L left, R right) {
this.left = left;
this.right = right;
}

public L getLeft() {
return left;
}

public R getRight() {
return right;
}

@Override
public int hashCode() {
return left.hashCode() ^ right.hashCode();
}

@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(left, pair.left) &&
Objects.equals(right, pair.right);
}

@Override
public String toString() {
return "(" + left + ", " + right + ")";
}

@Override
public int compareTo(Pair<L, R> other) {
int cmp = ((Comparable<L>) this.left).compareTo(other.left);
if (cmp != 0) {
return cmp;
}
return ((Comparable<R>) this.right).compareTo(other.right);
}
}


#Java #Training #Medium #Pair
Особенности этой реализации:

Реализация интерфейса Map.Entry: Этот интерфейс позволяет использовать
Pair в контексте ключ-значение, например, в HashMap. Это делает класс более универсальным.
Имплементация Comparable: Это позволяет сравнивать пары между собой, если элементы пары реализуют интерфейс Comparable. Это полезно для сортировки списков пар.
Иммутабельность: Поля left и right являются final, что обеспечивает неизменяемость пары после её создания.
Реализация Serializable: Это позволяет сериализовать объекты класса
Pair, что важно для сохранения состояния объектов, передачи их по сети и т.д.
Переопределение hashCode и equals: Эти методы позволяют использовать пары в коллекциях, таких как HashSet и HashMap, где важно правильное определение уникальности объектов.


Сравнение Pair с другими структурами данных

Класс Pair можно сравнить с другими структурами данных, такими как массивы, кортежи (tuples) и пользовательские классы:
Массивы: Массивы могут использоваться для хранения пары значений, однако они менее удобны, так как не обеспечивают типизацию и не дают возможности явно указать, что первое и второе значение связаны друг с другом.


Object[] pairArray = {"John", 30};
String name = (String) pairArray[0];
Integer age = (Integer) pairArray[1];
В отличие от массива, Pair предоставляет более очевидный и безопасный способ работы с парными значениями.


Кортежи: В некоторых языках программирования, таких как Python, существуют кортежи, которые являются аналогом Pair в Java. В Java для работы с несколькими связанными значениями часто используют Pair.
Пользовательские классы: В случае, когда пара значений имеет более сложное поведение или требует дополнительных методов, можно создать собственный класс, который будет представлять собой пару. Однако в большинстве случаев использование
Pair предпочтительно, так как оно упрощает код.

public class Person {
private final String name;
private final int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

// Методы get, equals, hashCode и другие
}
Если же пара значений не требует дополнительных методов и логики, то Pair — идеальное решение.


#Java #Training #Medium #Pair
Основные методы класса Pair

Класс Pair, независимо от конкретной реализации (например, Apache Commons, JavaFX, или собственная реализация), предлагает несколько ключевых методов, которые делают работу с парами значений удобной и эффективной.

Конструктор Pair(K key, V value)

Конструктор используется для создания новой пары. Он принимает два параметра — key и value, которые инициализируют соответствующие поля объекта Pair.
Pair<String, Integer> pair = new Pair<>("John", 30);
В этом примере создается пара, где ключом (или первым элементом) является строка "John", а значением (или вторым элементом) — целое число 30.


Методы getKey() и getValue()

Эти методы используются для получения значений, хранящихся в паре. Метод getKey() возвращает первый элемент пары (ключ), а getValue() — второй элемент (значение).
String name = pair.getKey();  // "John"
Integer age = pair.getValue(); // 30
Эти методы позволяют извлекать значения из объекта Pair, что удобно при работе с парными данными.


Методы equals() и hashCode()

Методы equals() и hashCode() переопределяются в классе Pair для обеспечения корректного сравнения и использования объекта в коллекциях, таких как HashMap или HashSet.
Pair<String, Integer> pair1 = new Pair<>("John", 30);
Pair<String, Integer> pair2 = new Pair<>("John", 30);

boolean areEqual = pair1.equals(pair2); // true
Метод equals() сравнивает два объекта Pair на предмет их равенства, основываясь на значениях ключа и значения. hashCode() возвращает хэш-код объекта, что важно для корректной работы с хешированными коллекциями.


Метод toString()

Метод toString() переопределяется для получения строкового представления объекта Pair. Обычно оно имеет вид (key, value).
System.out.println(pair.toString()); // (John, 30)
Этот метод полезен для вывода информации о паре в читаемом формате.


Метод compareTo(Pair<K, V> other)

Если класс Pair реализует интерфейс Comparable, то в нём будет присутствовать метод compareTo(). Он позволяет сравнивать два объекта Pair по их ключам и значениям. Это полезно для сортировки коллекций пар.
Pair<String, Integer> pair1 = new Pair<>("John", 30);
Pair<String, Integer> pair2 = new Pair<>("Alice", 25);

int comparisonResult = pair1.compareTo(pair2); // результат зависит от реализации Comparable
Этот метод особенно полезен, когда нужно отсортировать список объектов Pair по ключам или значениям.



Примеры использования класса Pair

Пример 1: Использование Pair в методах
Pair может быть полезен, когда нужно вернуть из метода два значения.
public class MinMaxExample {
public static Pair<Integer, Integer> findMinMax(int[] array) {
if (array == null || array.length == 0) {
throw new IllegalArgumentException("Array cannot be null or empty");
}

int min = array[0];
int max = array[0];

for (int num : array) {
if (num < min) {
min = num;
}
if (num > max) {
max = num;
}
}

return new Pair<>(min, max);
}

public static void main(String[] args) {
int[] numbers = {3, 5, 1, 8, -2, 7};
Pair<Integer, Integer> result = findMinMax(numbers);
System.out.println("Min: " + result.getKey());
System.out.println("Max: " + result.getValue());
}
}
Этот пример показывает, как метод findMinMax возвращает объект Pair, содержащий минимальное и максимальное значения массива. Это более элегантный способ возврата двух связанных значений по сравнению с использованием массивов или пользовательских классов.


#Java #Training #Medium #Pair
Пример 2: Использование Pair в коллекциях

Pair также полезен для хранения пар ключ-значение в коллекциях. Например, предположим, что мы хотим хранить информацию о студентах и их оценках в виде списка пар.
import java.util.ArrayList;
import java.util.List;

public class StudentGradesExample {
public static void main(String[] args) {
List<Pair<String, Integer>> studentGrades = new ArrayList<>();

studentGrades.add(new Pair<>("Alice", 85));
studentGrades.add(new Pair<>("Bob", 90));
studentGrades.add(new Pair<>("Charlie", 78));

for (Pair<String, Integer> pair : studentGrades) {
System.out.println("Student: " + pair.getKey() + ", Grade: " + pair.getValue());
}
}
}
В этом примере мы создаем список студентов и их оценок, используя класс Pair. Это позволяет легко хранить и обрабатывать пары данных, связанных логически.


Пример 3: Использование Pair в многомерных структурах

Иногда Pair может использоваться для создания более сложных структур данных, таких как многомерные таблицы, графы и т.д.
import java.util.HashMap;
import java.util.Map;

public class GraphExample {
public static void main(String[] args) {
Map<Pair<String, String>, Integer> graph = new HashMap<>();

graph.put(new Pair<>("A", "B"), 5);
graph.put(new Pair<>("A", "C"), 10);
graph.put(new Pair<>("B", "C"), 3);

for (Map.Entry<Pair<String, String>, Integer> entry : graph.entrySet()) {
Pair<String, String> edge = entry.getKey();
Integer weight = entry.getValue();
System.out.println("Edge from " + edge.getKey() + " to " + edge.getValue() + " has weight " + weight);
}
}
}
Этот пример показывает, как Pair может быть использован в качестве ключа в HashMap, чтобы хранить ребра графа и их веса. Это полезно для представления связей между узлами в графе.


Пример 4: Объединение значений из двух массивов

Рассмотрим пример, когда у нас есть два массива — один с именами студентов, другой с их оценками. Мы можем объединить их в список пар:
public class CombineArraysExample {
public static List<Pair<String, Integer>> combine(String[] names, int[] grades) {
List<Pair<String, Integer>> result = new ArrayList<>();
for (int i = 0; i < names.length; i++) {
result.add(new Pair<>(names[i], grades[i]));
}
return result;
}

public static void main(String[] args) {
String[] students = {"Alice", "Bob", "Charlie"};
int[] grades = {85, 90, 78};

List<Pair<String, Integer>> studentGrades = combine(students, grades);

for (Pair<String, Integer> pair : studentGrades) {
System.out.println(pair.getKey() + ": " + pair.getValue());
}
}
}
Этот код объединяет два массива в список объектов Pair, где каждый объект представляет пару "имя-оценка". Это упрощает доступ к связанной информации и её обработку.


#Java #Training #Medium #Pair