Использование пар или 2-кортежей в Java

Мой Hashtable в Java выиграет от значения, имеющего структуру кортежа. Какую структуру данных я могу использовать в Java для этого?

Hashtable<Long, Tuple<Set,Set>> table = ... 

Я не думаю, что в Java есть class универсального набора, но пользовательский способ может быть таким же простым, как и следующее:

 public class Tuple { public final X x; public final Y y; public Tuple(X x, Y y) { this.x = x; this.y = y; } } 

Конечно, есть некоторые важные последствия того, как создать этот class в дальнейшем относительно равенства, неизменности и т. Д., Особенно если вы планируете использовать экземпляры в качестве ключей для хеширования.

javatuples – выделенный проект для кортежей в Java.

 Unit (1 element) Pair (2 elements) Triplet (3 elements) 

Apache Commons предоставил некоторые распространенные утилиты java, включая Pair . Он реализует Map.Entry , Map.Entry и Serializable .

Если вы ищете встроенный двухэлементный кортеж Java, попробуйте AbstractMap.SimpleEntry .

В качестве дополнения к @maerics хороший ответ, я добавил несколько полезных методов:

 public class Tuple { 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 other_ = (Tuple) 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, для этого теперь есть class для стандартного Lib: javafx.util.Pair.

И да, это стандартная Java, теперь JavaFx включен в JDK 🙂

Вот этот тот же самый вопрос в другом месте, который включает в себя более надежные equals hash которые майеры ссылаются на:

http://groups.google.com/group/comp.lang.java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b

В этом обсуждении мы рассмотрим подходы maerics vs ColinD к «следует ли повторно использовать class Tuple с неспецифическим именем или создавать новый class с определенными именами каждый раз, когда я сталкиваюсь с этой ситуацией». Несколько лет назад я был в последнем лагере; Я превратился в поддержку первого.

Android Tuple Utils

Этот объект обеспечивает разумную реализацию equals (), возвращая true, если equals () истинно для каждого из содержащихся объектов.

Создайте class, который описывает концепцию, которую вы на самом деле моделируете и используете. Он может просто сохранить два Set и предоставить для них аксессоры, но он должен быть назван, чтобы указать, что именно представляет собой каждый из этих наборов и почему они сгруппированы вместе.

Чтобы дополнить ответ @ maerics, вот Comparable кортеж:

 import java.util.*; /** * A tuple of two classes that implement Comparable */ public class ComparableTuple, Y extends Comparable> extends Tuple implements Comparable> { public ComparableTuple(X x, Y y) { super(x, y); } /** * Implements lexicographic order */ public int compareTo(ComparableTuple other) { int d = this.x.compareTo(other.x); if (d == 0) return this.y.compareTo(other.y); return d; } } 

С lombok легко объявить class Pair :

 @Data(staticConstructor = "of") public class Pair { private final A left; private final B right; } 

Это создаст геттеры, статический конструктор с именем «из», equals() , hashcode() и toString() .

см. документацию @Data для получения дополнительной информации

Вы можете использовать таблицу Google Guava

Хотя статья довольно старая, и хотя я понимаю, что я не очень-то очень полезен, я думаю, что работа, проделанная здесь: 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); 

Здесь кортежи:

  • Определены как примитивные типы – нет шаблонов / дженериков
  • Выделение стека, если оно объявлено локально
  • Назначение с использованием сопоставления с образцом

Этот подход увеличивается

  • Представление
  • читабельность
  • Выразительность

Я начну с общей точки зрения о кортежах в Java и закончу с учетом вашей конкретной проблемы.

1) Путь кортежей используется в не-generic языках в Java избегается, потому что они не являются безопасными для типов (например, в Python: tuple = (4, 7.9, 'python') ). Если вы все еще хотите использовать что-то вроде кортежа общего назначения (что не рекомендуется ), вы должны использовать Object[] или List и лить элементы после проверки с помощью instanceof чтобы обеспечить безопасность типов.

Обычно кортежи в определенной настройке всегда используются одинаково с тем же содержимым. В Java вы должны явно определить эту структуру в class чтобы обеспечить четкие, безопасные по типу значения и методы. Вначале это кажется раздражающим и ненужным, но предотвращает ошибки уже во время компиляции .

2) Если вам нужен кортеж, содержащий те же (супер-) classы Foo , используйте Foo[] , List или List List (или неизменные копии списков). Поскольку кортеж не имеет определенной длины, это решение эквивалентно.

3) В вашем случае вам, похоже, нужна Pair (т. Е. Кортеж с четко определенной длиной 2). Это дает ответ maerics или один из дополнительных ответов наиболее эффективный, поскольку вы можете повторно использовать код в будущем.

Давайте будем гением компьютера.