Есть ли веская причина, почему нет Pair<L,R>
в Java? Что будет эквивалентно этой конструкции C ++? Я бы предпочел не реализовывать свое собственное.
Кажется, что 1.6 предоставляет нечто подобное ( AbstractMap.SimpleEntry<K,V>
), но это выглядит довольно запутанным.
AbstractMap.SimpleEntry
запутанный?Ответы:
В потоке на
comp.lang.java.help
Хантер Gratzner дает некоторые аргументы против присутствияPair
конструкции в Java. Основным аргументом является то, что классPair
не передает никакой семантики о связи между двумя значениями (как вы узнаете, что означают «первое» и «второе»?).Лучше всего написать очень простой класс, подобный тому, который предложил Майк, для каждого приложения, которое вы сделали бы для этого
Pair
класса.Map.Entry
Это пример пары, которая несет в себе свое значение.Подводя итог, на мой взгляд, лучше иметь класс
Position(x,y)
, классRange(begin,end)
и класс,Entry(key,value)
а не универсальный,Pair(first,second)
который ничего не говорит мне о том, что он должен делать.источник
Это Java. Вы должны создать свой собственный класс Pair с описательными именами классов и полей, не говоря уже о том, что вы заново изобретете колесо, написав hashCode () / equals () или снова и снова реализуя Comparable.
источник
SimpleImmutableEntry
HashMap совместимый класс пары:
источник
super()
. Обычно я бы просто отрубил это, если это необязательно, как здесь.Самая короткая пара, которую я смог придумать, это следующая, используя Lombok :
Он имеет все преимущества ответа от @arturh (кроме сравнимости), то есть
hashCode
,equals
,toString
и статический «конструктор».источник
В Apache Commons Lang 3.0+ есть несколько классов Pair: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html.
источник
Еще один способ реализации Pair with.
Простая фабрика, поэтому вам не нужно указывать типы. например, Pair.of ("привет", 1);
источник
of
. Это напоминает неизменные коллекции Google Guava .o1
к немуComparable
, даже если ничто не указывает на то, что он фактически реализует этот интерфейс. Если это требование,FIRST
параметр типа должен бытьFIRST extends Comparable<?>
.Как насчет http://www.javatuples.org/index.html Я нашел это очень полезным.
Javatuples предлагает вам классы кортежей от одного до десяти элементов:
источник
Pair
и мог предположить, чтобы использоватьTriplet
возможно один раз каждые 50 лет. Теперь я использую Lombok и создаю крошечный 4-строчный класс каждый раз, когда мне нужна пара. Так что «10 слишком много» - это точно.Bottom (0 element)
класс? :)Это зависит от того, для чего вы хотите его использовать. Типичная причина для этого - перебирать карты, для чего вы просто делаете это (Java 5+):
источник
Android обеспечивает
Pair
класс ( http://developer.android.com/reference/android/util/Pair.html ), здесь реализация:источник
Objects.equal(..)
требует библиотеки Guava.Objects.equals(...)
который был в Java с 2011 года (1.7).Самая большая проблема, вероятно, заключается в том, что невозможно обеспечить неизменность на A и B (см. Как обеспечить неизменность параметров типа ), поэтому
hashCode()
может дать противоречивые результаты для одной и той же пары после того, как она будет вставлена в коллекцию, например (это приведет к неопределенному поведению см. Определение равных в терминах изменяемых полей ). Для определенного (не универсального) класса Pair программист может обеспечить неизменность, тщательно выбирая A и B как неизменяемые.В любом случае, очистка предупреждений генерика от ответа @ PeterLawrey (Java 1.7):
Дополнения / исправления приветствуются :) В частности, я не совсем уверен в своем использовании
Pair<?, ?>
.Для получения дополнительной информации о том, почему этот синтаксис см. В разделе Убедитесь, что объекты реализуют Comparable, а также для подробного объяснения, как реализовать универсальную
max(Comparable a, Comparable b)
функцию в Java?источник
По моему мнению, в Java нет Pair, потому что, если вы хотите добавить дополнительные функции непосредственно в пару (например, Comparable), вы должны связать типы. В C ++ нам просто все равно, и если типы, составляющие пару, не имеют
operator <
, тоpair::operator <
компиляция также не будет.Пример Comparable без ограничений:
Пример Comparable с проверкой во время компиляции для сопоставимости аргументов типа:
Это хорошо, но на этот раз вы не можете использовать несопоставимые типы в качестве аргументов типа в Pair. Можно использовать множество компараторов для пары в каком-то служебном классе, но люди на C ++ могут этого не получить. Другой способ - написать множество классов в иерархии типов с разными границами для аргументов типа, но существует слишком много возможных границ и их комбинаций ...
источник
JavaFX (который поставляется в комплекте с Java 8) имеет класс Pair <A, B>
источник
hashCode()
. Обратите внимание, что сама Java не вызывает этот метод. Это для пользовательского кода, включая библиотеки.Как уже говорили многие другие, это действительно зависит от варианта использования, является ли класс Pair полезным или нет.
Я думаю, что для частной вспомогательной функции вполне законно использовать класс Pair, если это делает ваш код более читабельным и не стоит усилий для создания еще одного класса значений со всем его кодом.
С другой стороны, если ваш уровень абстракции требует, чтобы вы четко документировали семантику класса, который содержит два объекта или значения, то вы должны написать для него класс. Обычно это тот случай, если данные являются бизнес-объектом.
Как всегда, это требует квалифицированного суждения.
Для вашего второго вопроса я рекомендую класс Pair из библиотек Apache Commons. Они могут рассматриваться как расширенные стандартные библиотеки для Java:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
Возможно, вы также захотите взглянуть на EqualsBuilder , HashCodeBuilder и ToStringBuilder из Apache Commons , которые упрощают написание классов значений для ваших бизнес-объектов.
источник
Вы можете использовать служебный класс javafx,
Pair
который служит той же цели, что и pair <> в c ++.https://docs.oracle.com/javafx/2/api/javafx/util/Pair.htmlисточник
Хорошие новости
JavaFX
имеет ключевое значение пара.просто добавьте javafx в качестве зависимости и импортируйте
javafx.util.Pair
;и использовать просто как в
c++
.например
источник
Интерфейс Map.Entry очень близок к паре c ++. Посмотрите на конкретную реализацию, такую как AbstractMap.SimpleEntry и AbstractMap.SimpleImmutableEntry. Первый элемент - это getKey (), а второй - getValue ().
источник
источник
В соответствии с природой языка Java, я полагаю, что людям на самом деле не нужен
Pair
интерфейс, обычно это то, что им нужно. Вот пример:Итак, когда люди хотят вернуть два значения, они могут сделать следующее:
Это довольно легкое решение, и оно отвечает на вопрос «Что такое семантика a
Pair<L,R>
?». Ответ таков: это интерфейсная сборка с двумя (может быть разными) типами, и у нее есть методы для возврата каждого из них. Это зависит от вас, чтобы добавить дополнительную семантику к нему. Например, если вы используете позиции и действительно хотите , чтобы указать его в вас коде, вы можете определитьPositionX
иPositionY
что содержитInteger
, чтобы сделать вверхPair<PositionX,PositionY>
. Если JSR 308 доступен, вы также можете использоватьPair<@PositionX Integer, @PositionY Ingeger>
для упрощения.РЕДАКТИРОВАТЬ: Одна вещь, которую я должен указать здесь, - то, что вышеупомянутое определение явно связывает имя параметра типа и имя метода. Это ответ на те аргументы, что
Pair
нехватка семантической информации. Собственно, методgetL
означает «дай мне элемент, соответствующий типу параметра типа L», что означает что-то.РЕДАКТИРОВАТЬ: Вот простой полезный класс, который может сделать жизнь проще:
Применение:
источник
equals
,hashCode
аtoString
?toString
вам нужно больше знаний об отношениях между двумя полями.class
может быть лучше, чем простоinterface
потому, что оно может реализовать эти вещи.Несмотря на синтаксическое сходство, Java и C ++ имеют очень разные парадигмы. Написание C ++ как Java - плохой C ++, а написание Java как C ++ - плохой Java.
В среде IDE, основанной на отражении, такой как Eclipse, написание обязательной функциональности «парного» класса происходит быстро и просто. Создайте класс, определите два поля, используйте различные опции меню «Создать XX», чтобы заполнить класс за считанные секунды. Может быть, вам придется набирать «сравнить» очень быстро, если вы хотите интерфейс Comparable.
С отдельными опциями объявления / определения в языке C ++ генераторы кода не так хороши, поэтому написание небольших служебных классов требует больше времени. Поскольку пара является шаблоном, вам не нужно платить за функции, которые вы не используете, а средство typedef позволяет присваивать значимые типы названий кода, поэтому возражения по поводу «без семантики» на самом деле не поддерживаются.
источник
Пара была бы хорошей вещью, например, базовой структурой для сложных обобщений, это из моего кода:
Это так же, как кортеж Хаскелла
источник
Pair
оптимально, так как нет особой семантики. Хорошо иметь четкое название для ясной концепции, но искать имя, где «первое» и «второе» работают хорошо, - нет.Простой способ Object [] - можно использовать как любой кортеж
источник
Для языков программирования, таких как Java, альтернативная структура данных, используемая большинством программистов для представления парных структур данных, представляет собой два массива, и доступ к данным осуществляется через один и тот же индекс.
пример: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
Это не идеально, поскольку данные должны быть связаны друг с другом, но также оказываются довольно дешевыми. Кроме того, если ваш сценарий использования требует сохранения координат, то лучше создать собственную структуру данных.
У меня есть что-то подобное в моей библиотеке
источник
Вы можете использовать библиотеку Google AutoValue - https://github.com/google/auto/tree/master/value .
Вы создаете очень маленький абстрактный класс и аннотируете его с помощью @AutoValue, а процессор аннотаций генерирует для вас конкретный класс, который имеет значение семантическое.
источник
Вот несколько библиотек, которые имеют несколько степеней кортежей для вашего удобства:
Другие библиотеки были упомянуты, чтобы содержать по крайней мере
Pair
кортеж.В частности, в контексте функционального программирования, которое использует большую часть структурной типизации, а не номинальной типизации ( как указано в принятом ответе ), эти библиотеки и их кортежи очень удобны.
источник
Брайан Гетц, Пол Сандос и Стюарт Маркс объясняют, почему во время сессии QA в Devoxx'14.
Наличие общего класса пар в стандартной библиотеке превратится в технический долг, как только будут введены типы значений .
Смотрите также: есть ли в Java SE 8 пары или кортежи?
источник
другая краткая реализация ломбок
источник
Я заметил, что все реализации Pair разбросаны здесь по атрибуту, означающему порядок двух значений. Когда я думаю о паре, я имею в виду комбинацию из двух пунктов, в которой порядок двух не имеет значения. Вот моя реализация неупорядоченной пары с
hashCode
иequals
переопределяет для обеспечения желаемого поведения в коллекциях. Также клонируется.Эта реализация была должным образом проверена модулем, и было опробовано использование в наборе и карте.
Обратите внимание, я не утверждаю, что опубликовать это в открытом доступе. Это код, который я только что написал для использования в приложении, поэтому, если вы собираетесь его использовать, пожалуйста, воздержитесь от прямого копирования и немного возитесь с комментариями и именами. Поймать мой занос?
источник
Если кому-то нужна очень простая и легкая в использовании версия, я сделал ее доступной по адресу https://github.com/lfac-pt/Java-Pair . Кроме того, улучшения приветствуются!
источник
com.sun.tools.javac.util.Pair - простая реализация пары. Его можно найти в jdk1.7.0_51 \ lib \ tools.jar.
Кроме org.apache.commons.lang3.tuple.Pair, это не просто интерфейс.
источник
Применение :
Неизменный, только пара!
источник
Pair<Object, Object> pair = Pair.createPair("abc", "def")
но я полагаю, что нужно писатьPair.createPair((Object)"abc", (Object)"def")
с вашим кодом?@SuppressWarnings("unchecked") public static <K, V, X, Y> Pair<X, Y> createPair(K key, V value) { return new Pair<X, Y>((X) key, (Y) value); }
но я не знаю, хорошая ли это практикаnew Pair<Object, Object>("abc", "def")
был самым надежным в моих экспериментах.