Tuple (unmodifiable ordered list of heterogeneous elements) support in Java
Solution 1
The "Java way" is to define use-specific classes rather than these sorts of lightweight semi-class types. If you think about it, a tuple is really just a simplified struct; the Java folks would prefer you to just go ahead and create the struct.
This perspective is changing a bit, especially in Java 8 with its lambdas (which put pressure on the JDK to provide generic Function
-type interfaces rather than use-case-specific interfaces like FooCallback
). But it's still a fairly strong mindset for a lot of Java developers, and there's some sense to it. Java is a very statically typed language; a tuple is somewhere between static typing and dynamic typing, in that there's nothing in the type system to prevent you from thinking this (int, String)
that represents a customer ID and name is actually an (int, String)
representing an order ID and its description.
See, for instance, this discussion ("Tuples for n >= 2") on the issue within the Guava project. Granted, that's not official; but it's a good representation of the Java mindset.
Solution 2
There is a nice library called javatuples
. It defines generic tuple types for arities from 1(Unit
) to 10(Decade
) and all essential methods like equals
, hashCode
, toString
and even compareTo
.
Official site: http://www.javatuples.org/
Maven dependency:
<dependency>
<groupId>org.javatuples</groupId>
<artifactId>javatuples</artifactId>
<version>[version]</version>
<scope>compile</scope>
</dependency>
(at the moment latest version is 1.2
)
Solution 3
It has:
Collections.unmodifiableList(yourList)
will do the trick.
I think that the versatility of the JCF makes the existence of explicit tuple datastructures unnecessary.
I assume that by tuple you mean an ordered immutable list of elements (according to the wikipedia definition).
As for the 3rd party library my power search on google yielded this, this and of course this.
Solution 4
There is a type in the Java runtime and it is called Entry. This is an interface inside Map and there are simple implementation of it inside AbstractMap.
http://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html
http://docs.oracle.com/javase/7/docs/api/java/util/AbstractMap.SimpleEntry.html
You can use it as a tuple for two members, you can even apply generics. I would think hard what I did wrong if ever I needed more elements than two. Probably worth it own class then.
Solution 5
A colleague and I were discussing this a few weeks ago. The only solution I could come up with was to internally store the values in a Map<Class, Object>
and have some accessor method getValue(Class)
. Otherwise, how do you access the values in your tuple? You can't have a generic Tuple
class with methods for each member, e.g. getInteger
, getString
, etc because those methods would not be known until runtime, when you create the tuple. This also means you could never have two members with the same type -- how would you be able to write such a class so that at runtime, it knew which object to retrieve?
Oleksandr Karaberov
Updated on June 15, 2022Comments
-
Oleksandr Karaberov almost 2 years
I wonder why Java doesn't have a tuple data structure implementation in its standard library. For instance C++ has a very good implementation of this fixed-size collection of heterogeneous values. The same in Haskell. In Java I only know javatuples and some support in Functional Java library via
Product
(P1 - P8
) types. I wonder whytuple
or at leastpair
not in standard library at all? Even Android SDK developers added their own implementation of 2-tuple (pair). -
Paul Bellora over 11 yearsHow does this answer the question?
-
José Roberto Araújo Júnior over 11 years@PaulBellora tuple = unmodifiable list
-
Oleksandr Karaberov over 11 yearsBy tuple I mean just a product algebraic data type. And as far as I know in imperative languages tuples sometimes implemented as mutable data structures
-
John B over 11 yearsFYI, Guava's
ImmutableList
is considered safer thanunmodifiableList
asunmodifiableList
can still result in aConcurrentModificationException
-
Paul Bellora over 11 years@JoséRobertoAraújoJúnior Understood - I read the OP's use of "heterogeneous" to mean something like
Tuple2<String, Integer>
etc. -
rtheunissen over 11 yearsHow would Generics not solve this?
Tuple<String, JComponent> tup = new Tuple<>(); ... panel.add(tup.getLast()); label.setText(tup.getFirst());
This is obviously a forced size of 2 tuple but it's easy enough to have an Object array underneath and have the programmer be responsible for casting. In all my years I've never found a situation where I've needed a tuple data structure where an easy alternative wasn't available. -
Adam Arold over 11 yearsI know about
ImmutableList
but it is not part of the JCF I was talking about. Thanks for pointing it out though. -
Thorn G over 11 yearsSo when you want more than 2 elements, what do you do? You can't write
getSecond
,getThird
, etc. You might as well just haveObject[]
at that point. -
rtheunissen over 11 yearsTuple structures of more than 2 more 3 elements would be a glorified
Object []
, where instead ofgetFirst()
getSecond()
you would haveget(index)
, which is hardly any different to anObject []
orList<Object>
. Quite often it might be nice to pair two types together, which for the most part becomes aMap
. -
Display Name almost 11 yearsThen why don't you create a class for every tuple of arity 1? There's nothing in the type system to prevent you from thinking this
int
that represents a customer ID is actually anint
representing an order ID. -
Display Name almost 11 yearsBTW, it's very easy to spot it by searching in google "java tuples".
-
yshavit almost 11 years@SargeBorsch In short, because Java isn't well designed for that pattern. Classes have overhead in performance, complexity (is it null?) and reflection (not a drop-in replacemtnt for an int). If you have to pay that cost anyway, you may as well do it right; if you don't, it's more of a balancing act. But to your point, I actually wish that Java did have something like Haskell's
newtype
, which would let you create a CustomerId which is a type-safe int. -
yshavit almost 11 yearsYup, Java draws a line in the sand between primitives and classes. No avoiding it.
-
Display Name almost 11 yearsBut all is not lost, there is some interesting workarounds in Scala. (unified type system, specialization, ...)
-
ymajoros almost 9 years@SargeBorsch I do just that wherever I can. Using id's instead of objects isn't the common path in most of my projects anyway.
-
Display Name over 8 yearsIn statically&strongly typed languages, tuple is more than just a fixed size list, because its type does contain information about the types of its elements. So N-element tuple has N type parameters. Lists have only one type parameter, that means, each list element has the same (compile-time) type.
-
Adam Arold over 8 yearsThere are a number of concepts which can be implemented in java but in a handicapped version. A good example might be a Trait or a Mixin. Therefore java developers are usually only implementing what is necessary. As you can see in my answer I assumed something which is based on the wikipedia definition.
-
BobDoolittle over 5 yearsI wish the "this dicussion" link still worked, I'm curious. I have the same intuition. Tuples like Pair feel like a concept that wandered out of Python and strayed into Java in a drunken stupor. There should be a better semantic binding between the elements so you know why they belong together and what their relationship is. Bob and Teri are a married couple, not just a Pair of people with an unknown relationship because their Author was too lazy to define marriage. Otherwise they could just be next-door neighbors, you wouldn't know.
-
yshavit over 5 years@BobDoolittle I found the page on the wayback machine and updated the link. Thanks for the nudge! That said, there isn't anything on that page that you didn't already know. :-) I originally posted this question a while ago, but I think I was mostly trying to cite a well-adopted project to say that this isn't just my opinion, it's shared by others.