Каков эквивалент C++ Pair<L,R> в Java?
Есть ли какая-то веская причина, почему в Java нет класса Pair<L,R>
? Какой эквивалент этому конструкцию из C++? Я бы предпочел избежать реализации собственного варианта.
Кажется, что в версии 1.6 появилась нечто похожее - AbstractMap.SimpleEntry<K,V>
, но это выглядит довольно запутанно.
5 ответ(ов)
Это Java. Вам нужно создать собственный класс Pair с описательными именами классов и полей, и не беспокоиться о том, что вы будете переизобретать колесо, реализуя методы hashCode()/equals() или снова и снова реализуя интерфейс Comparable.
Вот пример класса Pair
, совместимого с HashMap
в Java. Данный класс позволяет хранить пару значений и переопределяет методы hashCode()
и equals()
, что делает его подходящим для использования в коллекциях, таких как HashMap
.
public class Pair<A, B> {
private A first;
private B second;
public Pair(A first, B second) {
super();
this.first = first;
this.second = second;
}
@Override
public int hashCode() {
int hashFirst = first != null ? first.hashCode() : 0;
int hashSecond = second != null ? second.hashCode() : 0;
return (hashFirst + hashSecond) * hashSecond + hashFirst;
}
@Override
public boolean equals(Object other) {
if (other instanceof Pair) {
Pair<?, ?> otherPair = (Pair<?, ?>) other;
return
((this.first == otherPair.first ||
(this.first != null && otherPair.first != null &&
this.first.equals(otherPair.first))) &&
(this.second == otherPair.second ||
(this.second != null && otherPair.second != null &&
this.second.equals(otherPair.second)))) ;
}
return false;
}
@Override
public String toString() {
return "(" + first + ", " + second + ")";
}
public A getFirst() {
return first;
}
public void setFirst(A first) {
this.first = first;
}
public B getSecond() {
return second;
}
public void setSecond(B second) {
this.second = second;
}
}
Объяснение:
Переопределение
hashCode()
: Этот метод рассчитывает хеш-код на основе хеш-кодов обоих элементов. Это важно для того, чтобы объектыPair
корректно работали как ключи вHashMap
.Переопределение
equals()
: Этот метод проверяет, равны ли две пары. Он учитывает какnull
значения, так и значения объектов. Если оба значения совпадают, пары равны.Методы доступа (
getFirst()
,getSecond()
,setFirst()
,setSecond()
): Эти методы позволяют удобно работать с элементами пары, не нарушая инкапсуляцию.
Данный класс будет полезен в случаях, когда необходимо хранить совпадающие элементы в виде пар и использовать их в коллекциях, таких как HashMap
.
Apache Commons Lang 3.0 и новее предоставляет несколько классов Pair, которые можно найти в пакете org.apache.commons.lang3.tuple
. Это делается для удобной работы с парами значений.
Основные классы, которые предоставляются, включают Pair
, ImmutablePair
и MutablePair
. Каждый из этих классов имеет свои особенности:
Pair - это абстрактный базовый класс, который реализует общее поведение для пар.
ImmutablePair - это класс, который представляет пару значений, оба из которых неизменяемы. Когда вы создаете экземпляр
ImmutablePair
, значения не могут быть изменены после создания.MutablePair - этот класс позволяет изменять значения пар. Вы можете установить новые значения для обоих элементов после создания.
Для получения дополнительной информации и документации о том, как использовать эти классы, вы можете обратиться к официальной документации Apache Commons Lang.
Если у вас есть конкретный вопрос о том, как использовать классы Pair или о их функциональности, не стесняйтесь задавать его!
Если вы ищете другой способ реализации класса Pair
, то вот пример, который отвечает вашим требованиям:
- Публичные неизменяемые поля, т.е. простая структура данных.
- Реализует интерфейс
Comparable
. - Простая реализация методов
hashCode
иequals
. - Простая фабричная функция, позволяющая не указывать типы, например:
Pair.of("hello", 1);
Вот код для класса Pair
:
public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> {
public final FIRST first;
public final SECOND second;
private Pair(FIRST first, SECOND second) {
this.first = first;
this.second = second;
}
public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first, SECOND second) {
return new Pair<FIRST, SECOND>(first, second);
}
@Override
public int compareTo(Pair<FIRST, SECOND> o) {
int cmp = compare(first, o.first);
return cmp == 0 ? compare(second, o.second) : cmp;
}
// Может быть вынесен в вспомогательный класс.
private static int compare(Object o1, Object o2) {
return o1 == null ? (o2 == null ? 0 : -1) : (o2 == null ? 1 : ((Comparable) o1).compareTo(o2));
}
@Override
public int hashCode() {
return 31 * hashcode(first) + hashcode(second);
}
// Может быть вынесен в вспомогательный класс.
private static int hashcode(Object o) {
return o == null ? 0 : o.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
if (this == obj)
return true;
return equal(first, ((Pair) obj).first) && equal(second, ((Pair) obj).second);
}
// Может быть вынесен в вспомогательный класс.
private boolean equal(Object o1, Object o2) {
return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2));
}
@Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
Этот класс является универсальным и может использоваться для хранения пары значений с возможностью их сравнения, проверки на равенство и вычисления хеш-кода. Если у вас есть дополнительные вопросы или вам нужны доработки, дайте знать!
Вы можете рассмотреть библиотеку javatuples, которая, как я считаю, очень полезна.
Она предоставляет классы для работы с кортежами от одного до десяти элементов:
Unit<A> (1 элемент)
Pair<A,B> (2 элемента)
Triplet<A,B,C> (3 элемента)
Quartet<A,B,C,D> (4 элемента)
Quintet<A,B,C,D,E> (5 элементов)
Sextet<A,B,C,D,E,F> (6 элементов)
Septet<A,B,C,D,E,F,G> (7 элементов)
Octet<A,B,C,D,E,F,G,H> (8 элементов)
Ennead<A,B,C,D,E,F,G,H,I> (9 элементов)
Decade<A,B,C,D,E,F,G,H,I,J> (10 элементов)
Это может быть полезно, если вам нужно работать с фиксированными группами данных.
Инициализация ArrayList в одну строчку
Что значит 'synchronized'?
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?