My Hashtable в Java выиграет от значения, имеющего структуру кортежа. Какую структуру данных я могу использовать в Java для этого?
Hashtable<Long, Tuple<Set<Long>,Set<Long>>> table = ...
My Hashtable в Java выиграет от значения, имеющего структуру кортежа. Какую структуру данных я могу использовать в Java для этого?
Hashtable<Long, Tuple<Set<Long>,Set<Long>>> table = ...
Я не думаю, что в Java есть класс кортежей общего назначения, но пользовательский способ может быть таким же простым, как и следующее:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
Конечно, есть некоторые важные последствия того, как разработать этот класс в дальнейшем относительно равенства, неизменности и т.д., особенно если вы планируете использовать экземпляры как ключи для хэширования.
javatuples - выделенный проект для кортежей в Java.
Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Apache Commons предоставил некоторые общие утилиты java, включая Pair. Он реализует Map.Entry
, Comparable
и Serializable
.
Если вы ищете встроенный двухэлементный кортеж Java, попробуйте AbstractMap.SimpleEntry
.
Как расширение для @maerics приятного ответа, я добавил несколько полезных методов:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "(" + x + "," + y + ")";
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (!(other instanceof Tuple)){
return false;
}
Tuple<X,Y> other_ = (Tuple<X,Y>) other;
// this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed.
return other_.x.equals(this.x) && other_.y.equals(this.y);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((x == null) ? 0 : x.hashCode());
result = prime * result + ((y == null) ? 0 : y.hashCode());
return result;
}
}
Еще 2 цента: Начиная с Java 7, для этого теперь есть класс для стандартного Lib: javafx.util.Pair.
И да, это стандартная Java, теперь JavaFx включен в JDK:)
Здесь этот тот же самый вопрос в другом месте, включающий более надежные equals
, hash
, которые maerics ссылается на:
В этом обсуждении мы рассмотрим подходы maerics vs ColinD: "Должен ли я повторно использовать класс Tuple с неспецифическим именем или создавать новый класс с определенными именами каждый раз, когда я сталкиваюсь с этой ситуацией". Несколько лет назад я был в последнем лагере; Я превратился в поддержку первого.
Этот объект обеспечивает разумную реализацию equals(), возвращая true, если equals() истинно для каждого из содержащихся объектов.
Создайте класс, который описывает концепцию, которую вы на самом деле моделируете и используете. Он может просто сохранить два Set<Long>
и предоставить для них аксессуры, но он должен быть назван, чтобы указать, что именно каждый из этих наборов и почему они сгруппированы вместе.
Чтобы добавить ответ @maerics, вот тэг Comparable
:
import java.util.*;
/**
* A tuple of two classes that implement Comparable
*/
public class ComparableTuple<X extends Comparable<? super X>, Y extends Comparable<? super Y>>
extends Tuple<X, Y>
implements Comparable<ComparableTuple<X, Y>>
{
public ComparableTuple(X x, Y y) {
super(x, y);
}
/**
* Implements lexicographic order
*/
public int compareTo(ComparableTuple<X, Y> other) {
int d = this.x.compareTo(other.x);
if (d == 0)
return this.y.compareTo(other.y);
return d;
}
}
С lombok легко объявить класс Pair
:
@Data(staticConstructor = "of")
public class Pair<A, B> {
private final A left;
private final B right;
}
Это генерирует getters, статический конструктор с именем "из", equals()
, hashcode()
и toString()
.
см. @Data
для получения дополнительной информации
Вы можете использовать Таблица Google Guava
При правильном форматировании, делая его более новым разработчиком и исправляя ошибку в функции равных() Aram Kocharyan.
package ReplaceThisPackageName;
import java.util.Objects;
public class Pair<X, Y> extends Object{
public final X left;
public final Y right;
public Pair(X left, Y right) {
this.left = left;
this.right = right;
}
@Override
public String toString() {
return "(" + left + "," + right + ")";
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other == this) {
return true;
}
if (!(other instanceof Pair)) {
return false;
}
Pair<X, Y> other_ = (Pair<X, Y>) other;
return Objects.equals(other_.left, this.left) && Objects.equals(other_.right, this.right);
}
@Override
public int hashCode() {
final int prime = 13;
int result = 1;
result = prime * result + ((left == null) ? 0 : left.hashCode());
result = prime * result + ((right == null) ? 0 : right.hashCode());
return result;
}
}
Я начну с общей точки зрения о кортежах в Java и закончу с импликацией для вашей конкретной проблемы.
1) Использование кортежей в не общих языках избегается в Java, потому что они не являются безопасными для типов (например, в Python: tuple = (4, 7.9, 'python')
). Если вы все еще хотите использовать что-то вроде кортежей общего назначения (не рекомендуется), вы должны использовать Object[]
или List<Object>
и отбрасывать элементы после проверки с помощью instanceof
, чтобы гарантировать тип -Безопасность.
Обычно кортежи в определенной настройке всегда используются одинаково с той же структурой. В Java вы должны явно определить эту структуру в class
, чтобы обеспечить четкие, безопасные по типу значения и методы. Это сначала кажется раздражающим и ненужным, но предотвращает ошибки уже в время компиляции.
2) Если вам нужен кортеж, содержащий те же (супер-) классы Foo
, используйте Foo[]
, List<Foo>
или List<? extends Foo>
(или списки неизменяемых копий). Поскольку кортеж не имеет определенной длины, это решение эквивалентно.
3) В вашем случае вам, похоже, нужен Pair
(т.е. набор четкой длины 2). Это дает ответ maerics или один из дополнительных ответов наиболее эффективный, поскольку вы можете повторно использовать код в будущем.
Хотя статья довольно старая, и хотя я понимаю, что я не очень полезен, я думаю, что здесь проделана работа: http://www.pds.ewi.tudelft.nl/pubs/papers/cpe2005.pdf, было бы хорошо в основной Java.
Вы можете делать такие вещи, как:
int a;
char b;
float c;
[a,b,c] = [3,'a',2.33];
или
[int,int,char] x = [1,2,'a'];
или
public [int,boolean] Find(int i)
{
int idx = FindInArray(A,i);
return [idx,idx>=0];
}
[idx, found] = Find(7);
Здесь кортежи:
Этот подход увеличивает