Java doesn’t provide tuples. Here are some ideas what you can do about it.
Different Types of Tuples
There are very different situations where you need tuples. Two-tuples (pairs) are probably the most commonly used tuples and Java already has
Map.Entry. However, you must know exactly what kind of tuples you need. Here are some properties of tuples:
- mutable / immutable
- number of fields
- named fields / enumerated fields / both
- serializable, cloneable, compareable etc.
- tuple with special methods
There can’t be a general implementation of tuples because they can be so different. Can you change the sate of a tuple? Can you compare a pair to a triplet? This depends on how they will be used.
Arrays are not Tuples!
Since Java doesn’t provide tuples it’s often tempting to just use arrays. But they are always mutable and there’s no guarantee that all threads see the same content. So they are not suitable for parallel programming.
If you simply need a pair you could just use
java.util.Map.Entry<K, V>, but you’d still have to implement that interface unless you just use or extend
AbstractMap.SimpleEntry. A 1-tuple exists as
java.util.concurrent.atomic.AtomicReference. And then there is
java.util.Optional, which may or may not contain one value.
For a full set of implementations you can use a library such as:
In many cases this is the best option. Simply create a class or an interface for the type you need. You have full control what kind of mutations (if any) are allowed and you have meaningful names for the type and the fields. Tools can generate methods such as getters, setters,
equals. Then you can simply add any methods to that type and you do not need a utility class full of static methods for your tuples. Your tuples can be observable, comparable, serializeable etc.
java.util.Map is somewhat similar to a tuple. But you need to define the fields. For that you can use an
enum and then use an
EnumMap as the
Calendar works like that. It’s really a 17-tuple, with fields such as
HOUR_OF_DAY, etc. This exists since JDK1.1, before enums where added to Java. So instead of enum constants they used static
int fields and
Calendar doesn’t actually implement
Map<Integer, Integer>. The newer type
java.time.LocalDateTime (since Java 8) uses
TemporalField, which is implemented by the enum
ChronoField. So this maps
In some cases you can use a functional interface instead of a tuple. A method could return a
BiConsumer instead of a
Pair. If more values are needed a functional interface needs to be defined. The parameters of the consumer can have meaningful names. Another benefit is that it can be lazy (values are calculated on access only), but you need to handle the possibility that it gets called multiple times.