Does Java Se 8 Have Pairs or Tuples

Does Java SE 8 have Pairs or Tuples?

UPDATE: This answer is in response to the original question, Does Java SE 8 have Pairs or Tuples? (And implicitly, if not, why not?) The OP has updated the question with a more complete example, but it seems like it can be solved without using any kind of Pair structure. [Note from OP: here is the other correct answer.]


The short answer is no. You either have to roll your own or bring in one of the several libraries that implements it.

Having a Pair class in Java SE was proposed and rejected at least once. See this discussion thread on one of the OpenJDK mailing lists. The tradeoffs are not obvious. On the one hand, there are many Pair implementations in other libraries and in application code. That demonstrates a need, and adding such a class to Java SE will increase reuse and sharing. On the other hand, having a Pair class adds to the temptation of creating complicated data structures out of Pairs and collections without creating the necessary types and abstractions. (That's a paraphrase of Kevin Bourillion's message from that thread.)

I recommend everybody read that entire email thread. It's remarkably insightful and has no flamage. It's quite convincing. When it started I thought, "Yeah, there should be a Pair class in Java SE" but by the time the thread reached its end I had changed my mind.

Note however that JavaFX has the javafx.util.Pair class. JavaFX's APIs evolved separately from the Java SE APIs.

As one can see from the linked question What is the equivalent of the C++ Pair in Java? there is quite a large design space surrounding what is apparently such a simple API. Should the objects be immutable? Should they be serializable? Should they be comparable? Should the class be final or not? Should the two elements be ordered? Should it be an interface or a class? Why stop at pairs? Why not triples, quads, or N-tuples?

And of course there is the inevitable naming bikeshed for the elements:

  • (a, b)
  • (first, second)
  • (left, right)
  • (car, cdr)
  • (foo, bar)
  • etc.

One big issue that has hardly been mentioned is the relationship of Pairs to primitives. If you have an (int x, int y) datum that represents a point in 2D space, representing this as Pair<Integer, Integer> consumes three objects instead of two 32-bit words. Furthermore, these objects must reside on the heap and will incur GC overhead.

It would seem clear that, like Streams, it would be essential for there to be primitive specializations for Pairs. Do we want to see:

Pair
ObjIntPair
ObjLongPair
ObjDoublePair
IntObjPair
IntIntPair
IntLongPair
IntDoublePair
LongObjPair
LongIntPair
LongLongPair
LongDoublePair
DoubleObjPair
DoubleIntPair
DoubleLongPair
DoubleDoublePair

Even an IntIntPair would still require one object on the heap.

These are, of course, reminiscent of the proliferation of functional interfaces in the java.util.function package in Java SE 8. If you don't want a bloated API, which ones would you leave out? You could also argue that this isn't enough, and that specializations for, say, Boolean should be added as well.

My feeling is that if Java had added a Pair class long ago, it would have been simple, or even simplistic, and it wouldn't have satisfied many of the use cases we are envisioning now. Consider that if Pair had been added in the JDK 1.0 time frame, it probably would have been mutable! (Look at java.util.Date.) Would people have been happy with that? My guess is that if there were a Pair class in Java, it would be kinda-sort-not-really-useful and everybody will still be rolling their own to satisfy their needs, there would be various Pair and Tuple implementations in external libraries, and people would still be arguing/discussing about how to fix Java's Pair class. In other words, kind of in the same place we're at today.

Meanwhile, some work is going on to address the fundamental issue, which is better support in the JVM (and eventually the Java language) for value types. See this State of the Values document. This is preliminary, speculative work, and it covers only issues from the JVM perspective, but it already has a fair amount of thought behind it. Of course there are no guarantees that this will get into Java 9, or ever get in anywhere, but it does show the current direction of thinking on this topic.

Using Pairs or 2-tuples in Java

I don't think there is a general purpose tuple class in Java but a custom one might be as easy as the following:

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;
}
}

Of course, there are some important implications of how to design this class further regarding equality, immutability, etc., especially if you plan to use instances as keys for hashing.

Java8: How can I use Pair in Hashmap

tl;dr

record Pair ( String string , State state ) {}

Records

The Answer by Bykov is good if you want a general mutable pair class. Alternatively, you can whip up a specific immutable pairing quite easily in Java 16+ by using the records feature.

A record is a brief way to write a class whose main purpose is to communicate data transparently and immutably. You simply declare the type and name of each member field. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.

Here is our entire class definition in six words:

record Pair ( String string , State state ) {}

You would of course use more descriptive class and field names.

Instantiate like a conventional class.

Pair p = new Pair( "whatever" , tennessee ) ;

You can declare a record locally, as well as nested or separately.

That record above is equivalent to the conventional code seen below. Modern IDEs such IntelliJ can convert a record to a conventional class, creating this source code.

package work.basil.example;

import java.util.Objects;

public final class Pair {
private final String string;
private final State state;

public Pair ( String string , State state ) {
this.string = string;
this.state = state;
}

public String string () { return string; }

public State state () { return state; }

@Override
public boolean equals ( Object obj ) {
if ( obj == this ) return true;
if ( obj == null || obj.getClass () != this.getClass () ) return false;
var that = ( Pair ) obj;
return Objects.equals ( this.string , that.string ) &&
Objects.equals ( this.state , that.state );
}

@Override
public int hashCode () {
return Objects.hash ( string , state );
}

@Override
public String toString () {
return "Pair[" +
"string=" + string + ", " +
"state=" + state + ']';
}

}

A Java collection of value pairs? (tuples?)

The Pair class is one of those "gimme" generics examples that is easy enough to write on your own. For example, off the top of my head:

public class Pair<L,R> {

private final L left;
private final R right;

public Pair(L left, R right) {
assert left != null;
assert right != null;

this.left = left;
this.right = right;
}

public L getLeft() { return left; }
public R getRight() { return right; }

@Override
public int hashCode() { return left.hashCode() ^ right.hashCode(); }

@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) return false;
Pair pairo = (Pair) o;
return this.left.equals(pairo.getLeft()) &&
this.right.equals(pairo.getRight());
}

}

And yes, this exists in multiple places on the Net, with varying degrees of completeness and feature. (My example above is intended to be immutable.)

Didn't Java once have a Pair class?

There is no Pair in the standard framework, but the Apache Commons Lang, which comes quite close to “standard”, has a Pair.

new MutablePair<>(1, "xxx");
new ImmutablePair<>(1, "xxx");

What is the equivalent of the C++ PairL,R in Java?

In a thread on comp.lang.java.help, Hunter Gratzner gives some arguments against the presence of a Pair construct in Java. The main argument is that a class Pair doesn't convey any semantics about the relationship between the two values (how do you know what "first" and "second" mean ?).

A better practice is to write a very simple class, like the one Mike proposed, for each application you would have made of the Pair class. Map.Entry is an example of a pair that carry its meaning in its name.

To sum up, in my opinion it is better to have a class Position(x,y), a class Range(begin,end) and a class Entry(key,value) rather than a generic Pair(first,second) that doesn't tell me anything about what it's supposed to do.

Turning an array of Java8 streams into a stream of tuples

OK, it seeems there isn't anything like that around, so I've written it myself:

  • TupleSpliterator, to build a tuple spliterator starting from an array of spliterators;
  • Tuple Stream Builder, which builds a tuple stream, starting from an array of streams and exploiting a tuple iterator.
  • The Spliteraror/Iterator based allow for parallelism (under certain conditions), in case you want something simpler, but sequential, a TupleIterator is available as well.

Usage examples available in unit tests (here and here), the classes are part of this utility package.

EDIT: I've added the Spliterator implementation, after the comment from Federico, noticing that the Iterator-based version can't be parallel.



Related Topics



Leave a reply



Submit