Java get String CompareTo as a comparator object - java

I would like to sort and binary search a static array of strings via the String.CompareTo comparator.
The problem is that both sorting, and binary searching requires that a Comparator object be passed in -- So how do I pass in the built in string comparator?

You may write your own comparator
public class ExampleComparator implements Comparator<String> {
public int compare(String obj1, String obj2) {
if (obj1 == obj2) {
return 0;
}
if (obj1 == null) {
return -1;
}
if (obj2 == null) {
return 1;
}
return obj1.compareTo(obj2);
}
}

Solution for Java 8 based on java.util.Comparator.comparing(...):
Comparator<String> c = Comparator.comparing(String::toString);
or
Comparator<String> c = Comparator.comparing((String x) -> x);

The Arrays class has versions of sort() and binarySearch() which don't require a Comparator. For example, you can use the version of Arrays.sort() which just takes an array of objects. These methods call the compareTo() method of the objects in the array.

Ok this is a few years later but with java 8 you can use Comparator.naturalOrder():
http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#naturalOrder--
From javadoc:
static <T extends Comparable<? super T>> Comparator<T> naturalOrder()
Returns a comparator that compares Comparable objects in natural order.
The returned comparator is serializable and throws NullPointerException when comparing null.

If you do find yourslef needing a Comparator, and you already use Guava, you can use Ordering.natural().

This is a generic Comparator for any kind of Comparable object, not just String:
package util;
import java.util.Comparator;
/**
* The Default Comparator for classes implementing Comparable.
*
* #param <E> the type of the comparable objects.
*
* #author Michael Belivanakis (michael.gr)
*/
public final class DefaultComparator<E extends Comparable<E>> implements Comparator<E>
{
#SuppressWarnings( "rawtypes" )
private static final DefaultComparator<?> INSTANCE = new DefaultComparator();
/**
* Get an instance of DefaultComparator for any type of Comparable.
*
* #param <T> the type of Comparable of interest.
*
* #return an instance of DefaultComparator for comparing instances of the requested type.
*/
public static <T extends Comparable<T>> Comparator<T> getInstance()
{
#SuppressWarnings("unchecked")
Comparator<T> result = (Comparator<T>)INSTANCE;
return result;
}
private DefaultComparator()
{
}
#Override
public int compare( E o1, E o2 )
{
if( o1 == o2 )
return 0;
if( o1 == null )
return 1;
if( o2 == null )
return -1;
return o1.compareTo( o2 );
}
}
How to use with String:
Comparator<String> stringComparator = DefaultComparator.getInstance();

Again, don't need the comparator for Arrays.binarySearch(Object[] a, Object key) so long as the types of objects are comparable, but with lambda expressions this is now way easier.
Simply replace the comparator with the method reference: String::compareTo
E.g.:
Arrays.binarySearch(someStringArray, "The String to find.", String::compareTo);
You could also use
Arrays.binarySearch(someStringArray, "The String to find.", (a,b) -> a.compareTo(b));
but even before lambdas, there were always anonymous classes:
Arrays.binarySearch(
someStringArray,
"The String to find.",
new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});

Also, if you want case-insensitive comparison, in recent versions of Java the String class contains a public static final field called CASE_INSENSITIVE_ORDER which is of type Comparator<String>, as I just recently found out. So, you can get your job done using String.CASE_INSENSITIVE_ORDER.

We can use the String.CASE_INSENSITIVE_ORDER comparator to compare the strings in case insensitive order.
Arrays.binarySearch(someStringArray, "The String to find.",String.CASE_INSENSITIVE_ORDER);

To generalize the good answer of Mike Nakis with String.CASE_INSENSITIVE_ORDER, you can also use :
Collator.getInstance();
See Collator

Regarding Nambari's answer there was a mistake. If you compare values using double equal sign == program will never reach compare method, unless someone will use new keyword to create String object which is not the best practice. This might be a bit better solution:
public int compare(String o1, String o2) {
if (o1 == null && o2 == null){return 0;}
if (o1 == null) { return -1;}
if (o2 == null) { return 1;}
return o1.compareTo(o2);
}
P.S. Thanks for comments ;)

You can use the StringUtils.compare("a", "b")

Related

Is there a simple way in Java to get the difference between two collections using a custom equals function without overriding the equals?

I'm open to use a lib. I just want something simple to diff two collections on a different criteria than the normal equals function.
Right now I use something like :
collection1.stream()
.filter(element -> !collection2.stream()
.anyMatch(element2 -> element2.equalsWithoutSomeField(element)))
.collect(Collectors.toSet());
and I would like something like :
Collections.diff(collection1, collection2, Foo::equalsWithoutSomeField);
(edit) More context:
Should of mentioned that I'm looking for something that exists already and not to code it myself. I might code a small utils from your ideas if nothing exists.
Also, Real duplicates aren't possible in my case: the collections are Sets. However, duplicates according to the custom equals are possible and should not be removed by this operation. It seems to be a limitation in a lot of possible solutions.
We use similar methods in our project to shorten repetitive collection filtering. We started with some basic building blocks:
static <T> boolean anyMatch(Collection<T> set, Predicate<T> match) {
for (T object : set)
if (match.test(object))
return true;
return false;
}
Based on this, we can easily implement methods like noneMatch and more complicated ones like isSubset or your diff:
static <E> Collection<E> disjunctiveUnion(Collection<E> c1, Collection<E> c2, BiPredicate<E, E> match)
{
ArrayList<E> diff = new ArrayList<>();
diff.addAll(c1);
diff.addAll(c2);
diff.removeIf(e -> anyMatch(c1, e1 -> match.test(e, e1))
&& anyMatch(c2, e2 -> match.test(e, e2)));
return diff;
}
Note that there are for sure some possibilities for perfomance tuning. But keeping it separated into small methods help understanding and using them with ease. Used in code they read quite nice.
You would then use it as you already said:
CollectionUtils.disjunctiveUnion(collection1, collection2, Foo::equalsWithoutSomeField);
Taking Jose Da Silva's suggestion into account, you could even use Comparator to build your criteria on the fly:
Comparator<E> special = Comparator.comparing(Foo::thisField)
.thenComparing(Foo::thatField);
BiPredicate specialMatch = (e1, e2) -> special.compare(e1, e2) == 0;
You can use UnifiedSetWithHashingStrategy from Eclipse Collections. UnifiedSetWithHashingStrategy allows you to create a Set with a custom HashingStrategy.
HashingStrategy allows the user to use a custom hashCode() and equals(). The Object's hashCode() and equals() is not used.
Edit based on requirement from OP via comment:
You can use reject() or removeIf() depending on your requirement.
Code Example:
// Common code
Person person1 = new Person("A", "A");
Person person2 = new Person("B", "B");
Person person3 = new Person("C", "A");
Person person4 = new Person("A", "D");
Person person5 = new Person("E", "E");
MutableSet<Person> personSet1 = Sets.mutable.with(person1, person2, person3);
MutableSet<Person> personSet2 = Sets.mutable.with(person2, person4, person5);
HashingStrategy<Person> hashingStrategy =
HashingStrategies.fromFunction(Person::getLastName);
1) Using reject(): Creates a new Set which contains all the elements which do not satisfy the Predicate.
#Test
public void reject()
{
MutableSet<Person> personHashingStrategySet = HashingStrategySets.mutable.withAll(
hashingStrategy, personSet2);
// reject creates a new copy
MutableSet<Person> rejectSet = personSet1.reject(personHashingStrategySet::contains);
Assert.assertEquals(Sets.mutable.with(person1, person3), rejectSet);
}
2) Using removeIf(): Mutates the original Set by removing the elements which satisfy the Predicate.
#Test
public void removeIfTest()
{
MutableSet<Person> personHashingStrategySet = HashingStrategySets.mutable.withAll(
hashingStrategy, personSet2);
// removeIf mutates the personSet1
personSet1.removeIf(personHashingStrategySet::contains);
Assert.assertEquals(Sets.mutable.with(person1, person3), personSet1);
}
Answer before requirement from OP via comment: Kept for reference if others might find it useful.
3) Using Sets.differenceInto() API available in Eclipse Collections:
In the code below, set1 and set2 are the two sets which use Person's equals() and hashCode(). The differenceSet is a UnifiedSetWithHashingStrategy so, it uses the lastNameHashingStrategy to define uniqueness. Hence, even though set2 does not contain person3 however it has the same lastName as person1 the differenceSet contains only person1.
#Test
public void differenceTest()
{
MutableSet<Person> differenceSet = Sets.differenceInto(
HashingStrategySets.mutable.with(hashingStrategy),
set1,
set2);
Assert.assertEquals(Sets.mutable.with(person1), differenceSet);
}
Person class common to both code blocks:
public class Person
{
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName()
{
return firstName;
}
public String getLastName()
{
return lastName;
}
#Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(lastName, person.lastName);
}
#Override
public int hashCode()
{
return Objects.hash(firstName, lastName);
}
}
Javadocs: MutableSet, UnifiedSet, UnifiedSetWithHashingStrategy, HashingStrategy, Sets, reject, removeIf
Note: I am a committer on Eclipse Collections
static <T> Collection<T> diff(Collection<T> minuend, Collection<T> subtrahend, BiPredicate<T, T> equals) {
Set<Wrapper<T>> w1 = minuend.stream().map(item -> new Wrapper<>(item, equals)).collect(Collectors.toSet());
Set<Wrapper<T>> w2 = subtrahend.stream().map(item -> new Wrapper<>(item, equals)).collect(Collectors.toSet());
w1.removeAll(w2);
return w1.stream().map(w -> w.item).collect(Collectors.toList());
}
static class Wrapper<T> {
T item;
BiPredicate<T, T> equals;
Wrapper(T item, BiPredicate<T, T> equals) {
this.item = item;
this.equals = equals;
}
#Override
public int hashCode() {
// all items have same hash code, check equals
return 1;
}
#Override
public boolean equals(Object that) {
return equals.test(this.item, ((Wrapper<T>) that).item);
}
}
Comparing
You can achieve this without the use of any library, just using java's Comparator
For instance, with the following object
public class A {
private String a;
private Double b;
private String c;
private int d;
// getters and setters
}
You can use a comparator like
Comparator<AA> comparator = Comparator.comparing(AA::getA)
.thenComparing(AA::getB)
.thenComparingInt(AA::getD);
This compares the fields a, b and the int d, skipping c.
The only problem here is that this won't work with null values.
Comparing nulls
One possible solution to do a fine grained configuration, that is allow to check for specific null fields is using a Comparator class similar to:
// Comparator for properties only, only writed to be used with Comparator#comparing
public final class PropertyNullComparator<T extends Comparable<? super T>>
implements Comparator<Object> {
private PropertyNullComparator() { }
public static <T extends Comparable<? super T>> PropertyNullComparator<T> of() {
return new PropertyNullComparator<>();
}
#Override
public int compare(Object o1, Object o2) {
if (o1 != null && o2 != null) {
if (o1 instanceof Comparable) {
#SuppressWarnings({ "unchecked" })
Comparable<Object> comparable = (Comparable<Object>) o1;
return comparable.compareTo(o2);
} else {
// this will throw a ccn exception when object is not comparable
#SuppressWarnings({ "unchecked" })
Comparable<Object> comparable = (Comparable<Object>) o2;
return comparable.compareTo(o1) * -1; // * -1 to keep order
}
} else {
return o1 == o2 ? 0 : (o1 == null ? -1 : 1); // nulls first
}
}
}
This way you can use a comparator specifying the allowed null fields.
Comparator<AA> comparator = Comparator.comparing(AA::getA)
.thenComparing(AA::getB, PropertyNullComparator.of())
.thenComparingInt(AA::getD);
If you don't want to define a custom comparator you can use something like:
Comparator<AA> comparator = Comparator.comparing(AA::getA)
.thenComparing(AA::getB, Comparator.nullsFirst(Comparator.naturalOrder()))
.thenComparingInt(AA::getD);
Difference method
The difference (A - B) method could be implemented using two TreeSets.
static <T> TreeSet<T> difference(Collection<T> c1,
Collection<T> c2,
Comparator<T> comparator) {
TreeSet<T> treeSet1 = new TreeSet<>(comparator); treeSet1.addAll(c1);
if (treeSet1.size() > c2.size()) {
treeSet1.removeAll(c2);
} else {
TreeSet<T> treeSet2 = new TreeSet<>(comparator); treeSet2.addAll(c2);
treeSet1.removeAll(treeSet2);
}
return treeSet1;
}
note: a TreeSet makes sense to be used since we are talking of uniqueness with a specific comparator. Also could perform better, the contains method of TreeSet is O(log(n)), compared to a common ArrayList that is O(n).
Why only a TreeSet is used when treeSet1.size() > c2.size(), this is because when the condition is not met, the TreeSet#removeAll, uses the contains method of the second collection, this second collection could be any java collection and its contains method its not guaranteed to work exactly the same as the contains of the first TreeSet (with custom comparator).
Edit (Given the more context of the question)
Since collection1 is a set that could contains repeated elements acording to the custom equals (not the equals of the object) the solution already provided in the question could be used, since it does exactly that, without modifying any of the input collections and creating a new output set.
So you can create your own static function (because at least i am not aware of a library that provides a similar method), and use the Comparator or a BiPredicate.
static <T> Set<T> difference(Collection<T> collection1,
Collection<T> collection2,
Comparator<T> comparator) {
collection1.stream()
.filter(element1 -> !collection2.stream()
.anyMatch(element2 -> comparator.compare(element1, element2) == 0))
.collect(Collectors.toSet());
}
Edit (To Eugene)
"Why would you want to implement a null safe comparator yourself"
At least to my knowledge there isn't a comparator to compare fields when this are a simple and common null, the closest that i know of is (to raplace my sugested PropertyNullComparator.of() [clearer/shorter/better name can be used]):
Comparator.nullsFirst(Comparator.naturalOrder())
So you would have to write that line for every field that you want to compare. Is this doable?, of course it is, is it practical?, i think not.
Easy solution, create a helper method.
static class ComparatorUtils {
public static <T extends Comparable<? super T>> Comparator<T> shnp() { // super short null comparator
return Comparator.nullsFirst(Comparator.<T>naturalOrder());
}
}
Do this work?, yes this works, is it practical?, it looks like, is it a great solution? well that depends, many people consider the exaggerated (and/or unnecessary) use of helper methods as an anti-pattern, (a good old article by Nick Malik). There are some reasons listed there, but to make things short, this is an OO language, so OO solutions are normally preferred to static helper methods.
"As stated in the documentation : Note that the ordering maintained by a set (whether or not an explicit comparator is provided must be consistent with equals if it is to correctly implement the Set interface. Further, the same problem would arise in the other case, when size() > c.size() because ultimately this would still call equals in the remove method. So they both have to implement Comparator and equals consistently for this to work correctly"
The javadoc says of TreeSet the following, but with a clear if:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface
Then says this:
See Comparable or Comparator for a precise definition of consistent with equals
If you go to the Comparable javadoc says:
It is strongly recommended (though not required) that natural orderings be consistent with equals
If we continue to read the javadoc again from Comparable (even in the same paragraph) says the following:
This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all key comparisons using its compareTo (or compare ) method, so two keys that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
By this last quote and with a very simple code debug, or even a reading, you can see the use of an internal TreeMap, and that all its derivated methods are based on the comparator, not the equals method;
"Why is this so implemented? because there is a difference when removing many elements from a little set and the other way around, as a matter of fact same stands for addAll"
If you go to the definition of removeAll you can see that its implementation is in AbstractSet, it is not overrided. And this implementation uses a contains from the argument collection when this is larger, the beavior of this contains is uncertain, it isn't necessary (nor probable) that the received collection (e.g. list, queue, etc) has/can define the same comparator.
Update 1:
This jdk bug is being discussed (and considerated to be fixed) in here https://bugs.openjdk.java.net/browse/JDK-6394757
pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
code/test:
package com.my;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Equator;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
public class Diff {
public static class FieldEquator<T> implements Equator<T> {
private final Function<T, Object>[] functions;
#SafeVarargs
public FieldEquator(Function<T, Object>... functions) {
if (Objects.isNull(functions) || functions.length < 1) {
throw new UnsupportedOperationException();
}
this.functions = functions;
}
#Override
public boolean equate(T o1, T o2) {
if (Objects.isNull(o1) && Objects.isNull(o2)) {
return true;
}
if (Objects.isNull(o1) || Objects.isNull(o2)) {
return false;
}
for (Function<T, ?> function : functions) {
if (!Objects.equals(function.apply(o1), function.apply(o2))) {
return false;
}
}
return true;
}
#Override
public int hash(T o) {
if (Objects.isNull(o)) {
return -1;
}
int i = 0;
Object[] vals = new Object[functions.length];
for (Function<T, Object> function : functions) {
vals[i] = function.apply(o);
i++;
}
return Objects.hash(vals);
}
}
#SafeVarargs
private static <T> Set<T> difference(Collection<T> a, Collection<T> b, Function<T, Object>... functions) {
if ((Objects.isNull(a) || a.isEmpty()) && Objects.nonNull(b) && !b.isEmpty()) {
return new HashSet<>(b);
} else if ((Objects.isNull(b) || b.isEmpty()) && Objects.nonNull(a) && !a.isEmpty()) {
return new HashSet<>(a);
}
Equator<T> eq = new FieldEquator<>(functions);
Collection<T> res = CollectionUtils.removeAll(a, b, eq);
res.addAll(CollectionUtils.removeAll(b, a, eq));
return new HashSet<>(res);
}
/**
* Test
*/
#Builder
#Getter
#ToString
public static class A {
String a;
String b;
String c;
}
public static void main(String[] args) {
Set<A> as1 = new HashSet<>();
Set<A> as2 = new HashSet<>();
A a1 = A.builder().a("1").b("1").c("1").build();
A a2 = A.builder().a("1").b("1").c("2").build();
A a3 = A.builder().a("2").b("1").c("1").build();
A a4 = A.builder().a("1").b("3").c("1").build();
A a5 = A.builder().a("1").b("1").c("1").build();
A a6 = A.builder().a("1").b("1").c("2").build();
A a7 = A.builder().a("1").b("1").c("6").build();
as1.add(a1);
as1.add(a2);
as1.add(a3);
as2.add(a4);
as2.add(a5);
as2.add(a6);
as2.add(a7);
System.out.println("Set1: " + as1);
System.out.println("Set2: " + as2);
// Check A::getA, A::getB ignore A::getC
Collection<A> difference = difference(as1, as2, A::getA, A::getB);
System.out.println("Diff: " + difference);
}
}
result:
Set1: [Diff.A(a=2, b=1, c=1), Diff.A(a=1, b=1, c=1), Diff.A(a=1, b=1, c=2)]
Set2: [Diff.A(a=1, b=1, c=6), Diff.A(a=1, b=1, c=2), Diff.A(a=1, b=3, c=1), Diff.A(a=1, b=1, c=1)]
Diff: [Diff.A(a=1, b=3, c=1), Diff.A(a=2, b=1, c=1)]

How to correctly initialize a Comparator?

I need to write a static method in a class MinTester that computes the "smallest" string
from an ArrayList collection using a comparator object:
public static String min(ArrayList<String> list, Comparator<String> comp)
I cannot use the Collections class to compute the minimum.
Here is what I have so far.
public class MinTester
{
public static String min(ArrayList<String> list, Comparator<String> comp)
{
String shortest = list.get(0);
for(String str : list) {
if ( comp.compare(str, shortest) < 0) {
shortest = str;
}
}
return shortest;
}
}
I am not getting any errors here from the method, So I try to test it in Main with this.
I get this error when trying to pass comp: Variable comp may not have been initialized
public static void main(String[] args)
{
// TODO code application logic here
MinTester s = new MinTester();
Comparator<String> comp;
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
String a = s.min(list,comp);//Error: Variable comp may not have been initialized
System.out.println(a);
}
Heres where I run into my problem.
I try
Comparator<String> comp = new Comparator<>();//Error:Comparator is abstract, cannot be instantiated
Comparator<String> comp = new MinTester();//Error: MinTester cannot be converted to Comparator<String>
Can anyone tell me the proper way to handle this Comparator? Im not sure if Im just trying to initialize it incorrectly, or if I'm missing something in my MinTester class.
You should write a class that implements Comparator<String> for this. A quick approach using anonymous class:
String a = s.min(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
Since you need to compare based on String length, just change the comparison logic in the compare method:
String a = s.min(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return (s1.length() > s2.length()) ? 1 : (s1.length() < s2.length()) ? -1 : 0;
}
});
If you happen to use Java 7, then use Integer#compare:
String a = s.min(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
If you use Java 8, you can use a lambda expression:
String a = s.min(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
Comparator is an interface; different classes can implement it in different ways to perform different kinds of comparisons. The reason why your method takes a Comparator is so that the caller can choose how the strings should be compared. Pass in a Comparator that does lexical (aka alphabetical) comparison, and you'll get the first string in lexical order. Pass in a Comparator that looks at string length, and you'll get the shortest string.
Since the String class already implements the Comparable interface — a sort of sibling to Comparator that lets a class define its own comparison method — here's a handy generic class that lets you use any Comparable through the Comparator interface:
public final class ComparableComparator<T extends Comparable<T>> implements Comparator<T> {
#Override
public int compare(final T a, final T b) {
return a.compareTo(b);
}
}
Pass one of those into your method and it'll compare the strings using the String class's own compareTo method.
Edit: In Java 8 or later, the Comparator.naturalOrder() method gives you the same thing, so you don't need to write the class above.
You do not need to use Comparator, at least not unless you want to modify the natural ordering of the string comparisons. Use the compareTo() method for the String class instead.
if (str.compareTo(shortest) < 0) {
shortest = str;
}
If at all you wish to modify the natural ordering, you can create a class which implements the Comparator interface and then pass an instance of this class to the compare() method. You can also define your own logic for the comparisons.
public class StringDescComparator implements Comparator<String> {
#Override
public int compare(String str1, String str2) {
// return str1.compareTo(str2); // For natural ordering
return -1 * str1.compareTo(str2); // For reversed ordering
}
}
Then you can use an instance of the above class to compare in the descending order such that: "b" < "a"
Comparator comp = new StringDescComparator();

Best possible "generic" implementation of Comparator?

We recently had some troubles migrating from Java 6 to 7 because we have tonns of Comparator implemented in a way they not fullfill the Comparable contract and throw a Exception using the new Timsort algorithms.
Edit: Input from User Marco Forberg and class signature
I now found a Comparator many of the others are extending from, the compare method looked like this:
#Override
public int compare(final T o1, final T o2) {
return 0;
}
And i changed it to this in the hope i cover most of the cases:
#Override
public int compare(final T o1, final T o2) {
//Case: XOR check for either s1 or s2 being null
if(o1 == null ^ o2 == null){
return (o1 == null) ? -1 : 1;
}
//Case: both are null
if(o1 == o2){
return 0;
}
//Case: Its Comparable!
if(o1 instanceof Comparable && o2 instanceof Comparable){
Comparable c1 = (Comparable) o1;
Comparable c2 = (Comparable) o2;
return ObjectUtils.compare(c1, c2);
}
//Case: We don't know (ran for years this way)
return 0;
}
The class signature looks like this:
public class MyComparator<T> implements Comparator<T> {
While ObjectUtils is from the Apache Commons 3 and provides a null-safe compare method (I know the time i call this none of the both objects can be null because of the previous checks and i could use c1.compare(c2) as well)
Did this improve the behavior of the "Base"-Comparator? (which i assume)
and i am right that this would basically cover the Comparable contract since the value 0 is now returned for non-comparable Objects?

Java Interface Comparator static compare

int compare(Object o1, Object o2)
Compares its two arguments for order.
For compare 2 objects o1 and o2 need do something like:
MyClass o1=new MyClass();
MyClass o2=new MyClass();
if (o1.compare(o1,o2)>0) ......
Why this methtod not static?
If method was static possible like:
if (MyClass.compare(o1,o2)>0) ....
If it were static, how could it be called polymorphically? The point of Comparator is that you can pass an instance into something like sort... which has to then call the compare method on the comparator instance.
If a class is capable of comparing one instance of itself to another, it should implement Comparable instead, so you'd write:
if (o1.compareTo(o2))
Your question shows a lack of understanding of Comparable and Comparator.
A Comparator is capable of comparing two other objects;
MyClass o1 = new MyClass();
MyClass o2 = new MyClass();
MyComparator c1 = new MyComparator();
if (c1.compare(o1, o2) > 0) {
...
}
Something which is Comparable is able to be compared to other objects;
MyClass o1 = new MyClass();
MyClass o2 = new MyClass();
if (o1.compareTo(o2)) > 0) {
...
}
It is very rare to compare a Comparator, so your example;
if (o1.compare(o1, o2) > 0) {
...
}
doesn't really make sense. Anyway, onto the answer, why isn't compareTo() static? Basically, Comparator is an interface, and interfaces can't have static methods. Why? Well, it doesn't make sense for them. An interface is about defining a contract, but providing no implementation.
The answer of John is fine unless null pointers are possible. If you want to support null pointers an option is to define a static method on some Util class
// null pointers first
public static int compareTo(#Nullable Comparable v1, #Nullable Comparable v2)
{
return v1 == null ? (v2 == null ? 0 : -1) : v2 == null ? 1 : v1.compareTo(v2);
}
// null pointers last
public static int compareTo(#Nullable Comparable v1, #Nullable Comparable v2)
{
return v1 == null ? (v2 == null ? 0 : 1) : v2 == null ? -1 : v1.compareTo(v2);
}

What is the equivalent of the C++ Pair<L,R> in Java?

Is there a good reason why there is no Pair<L,R> in Java? What would be the equivalent of this C++ construct? I would rather avoid reimplementing my own.
It seems that 1.6 is providing something similar (AbstractMap.SimpleEntry<K,V>), but this looks quite convoluted.
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.
This is Java. You have to make your own tailored Pair class with descriptive class and field names, and not to mind that you will reinvent the wheel by writing hashCode()/equals() or implementing Comparable again and again.
HashMap compatible Pair class:
public class Pair<A, B> {
private A first;
private B second;
public Pair(A first, B second) {
super();
this.first = first;
this.second = second;
}
public int hashCode() {
int hashFirst = first != null ? first.hashCode() : 0;
int hashSecond = second != null ? second.hashCode() : 0;
return (hashFirst + hashSecond) * hashSecond + hashFirst;
}
public boolean equals(Object other) {
if (other instanceof Pair) {
Pair otherPair = (Pair) other;
return
(( this.first == otherPair.first ||
( this.first != null && otherPair.first != null &&
this.first.equals(otherPair.first))) &&
( this.second == otherPair.second ||
( this.second != null && otherPair.second != null &&
this.second.equals(otherPair.second))) );
}
return false;
}
public String toString()
{
return "(" + first + ", " + second + ")";
}
public A getFirst() {
return first;
}
public void setFirst(A first) {
this.first = first;
}
public B getSecond() {
return second;
}
public void setSecond(B second) {
this.second = second;
}
}
The shortest pair that I could come up with is the following, using Lombok:
#Data
#AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
private F first;
private S second;
}
It has all the benefits of the answer from #arturh (except the comparability), it has hashCode, equals, toString and a static “constructor”.
Apache Commons Lang 3.0+ has a few Pair classes:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
Another way to implement Pair with.
Public immutable fields, i.e. simple data structure.
Comparable.
Simple hash and equals.
Simple factory so you don't have to provide the types. e.g. Pair.of("hello", 1);
public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> {
public final FIRST first;
public final SECOND second;
private Pair(FIRST first, SECOND second) {
this.first = first;
this.second = second;
}
public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first,
SECOND second) {
return new Pair<FIRST, SECOND>(first, second);
}
#Override
public int compareTo(Pair<FIRST, SECOND> o) {
int cmp = compare(first, o.first);
return cmp == 0 ? compare(second, o.second) : cmp;
}
// todo move this to a helper class.
private static int compare(Object o1, Object o2) {
return o1 == null ? o2 == null ? 0 : -1 : o2 == null ? +1
: ((Comparable) o1).compareTo(o2);
}
#Override
public int hashCode() {
return 31 * hashcode(first) + hashcode(second);
}
// todo move this to a helper class.
private static int hashcode(Object o) {
return o == null ? 0 : o.hashCode();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
if (this == obj)
return true;
return equal(first, ((Pair) obj).first)
&& equal(second, ((Pair) obj).second);
}
// todo move this to a helper class.
private boolean equal(Object o1, Object o2) {
return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2));
}
#Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
How about http://www.javatuples.org/index.html I have found it very useful.
The javatuples offers you tuple classes from one to ten elements:
Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Quartet<A,B,C,D> (4 elements)
Quintet<A,B,C,D,E> (5 elements)
Sextet<A,B,C,D,E,F> (6 elements)
Septet<A,B,C,D,E,F,G> (7 elements)
Octet<A,B,C,D,E,F,G,H> (8 elements)
Ennead<A,B,C,D,E,F,G,H,I> (9 elements)
Decade<A,B,C,D,E,F,G,H,I,J> (10 elements)
android provides Pairclass (http://developer.android.com/reference/android/util/Pair.html) , here the implementation:
public class Pair<F, S> {
public final F first;
public final S second;
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
return Objects.equal(p.first, first) && Objects.equal(p.second, second);
}
#Override
public int hashCode() {
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
}
public static <A, B> Pair <A, B> create(A a, B b) {
return new Pair<A, B>(a, b);
}
}
It depends on what you want to use it for. The typical reason to do so is to iterate over maps, for which you simply do this (Java 5+):
Map<String, Object> map = ... ; // just an example
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}
The biggest problem is probably that one can't ensure immutability on A and B (see How to ensure that type parameters are immutable) so hashCode() may give inconsistent results for the same Pair after is inserted in a collection for instance (this would give undefined behavior, see Defining equals in terms of mutable fields). For a particular (non generic) Pair class the programmer may ensure immutability by carefully choosing A and B to be immutable.
Anyway, clearing generic's warnings from #PeterLawrey's answer (java 1.7) :
public class Pair<A extends Comparable<? super A>,
B extends Comparable<? super B>>
implements Comparable<Pair<A, B>> {
public final A first;
public final B second;
private Pair(A first, B second) {
this.first = first;
this.second = second;
}
public static <A extends Comparable<? super A>,
B extends Comparable<? super B>>
Pair<A, B> of(A first, B second) {
return new Pair<A, B>(first, second);
}
#Override
public int compareTo(Pair<A, B> o) {
int cmp = o == null ? 1 : (this.first).compareTo(o.first);
return cmp == 0 ? (this.second).compareTo(o.second) : cmp;
}
#Override
public int hashCode() {
return 31 * hashcode(first) + hashcode(second);
}
// TODO : move this to a helper class.
private static int hashcode(Object o) {
return o == null ? 0 : o.hashCode();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
if (this == obj)
return true;
return equal(first, ((Pair<?, ?>) obj).first)
&& equal(second, ((Pair<?, ?>) obj).second);
}
// TODO : move this to a helper class.
private boolean equal(Object o1, Object o2) {
return o1 == o2 || (o1 != null && o1.equals(o2));
}
#Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
Additions/corrections much welcome :) In particular I am not quite sure about my use of Pair<?, ?>.
For more info on why this syntax see Ensure that objects implement Comparable and for a detailed explanation How to implement a generic max(Comparable a, Comparable b) function in Java?
Good News JavaFX has a key value Pair.
Just add JavaFX as a dependency and import javafx.util.Pair, and use simply as in C++.
Pair <Key, Value>
e.g.
Pair <Integer, Integer> pr = new Pair<Integer, Integer>()
pr.get(key);// will return corresponding value
In my opinion, there is no Pair in Java because, if you want to add extra functionality directly on the pair (e.g. Comparable), you must bound the types. In C++, we just don't care, and if types composing a pair do not have operator <, the pair::operator < will not compile as well.
An example of Comparable with no bounding:
public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static int compare(Object l, Object r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : ((Comparable) (l)).compareTo(r);
}
}
}
/* ... */
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
//Runtime error here instead of compile error!
System.out.println(a.compareTo(b));
An example of Comparable with compile-time check for whether type arguments are comparable:
public class Pair<
F extends Comparable<? super F>,
S extends Comparable<? super S>
> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static <
T extends Comparable<? super T>
> int compare(T l, T r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : l.compareTo(r);
}
}
}
/* ... */
//Will not compile because Thread is not Comparable<? super Thread>
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
System.out.println(a.compareTo(b));
This is good, but this time you may not use non-comparable types as type arguments in Pair.
One may use lots of Comparators for Pair in some utility class, but C++ people may not get it. Another way is to write lots of classes in a type hierarchy with different bounds on type arguments, but there are too many possible bounds and their combinations...
Map.Entry interface come pretty close to c++ pair. Look at the concrete implementation, like AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry
First item is getKey() and second is getValue().
According to the nature of Java language, I suppose people do not actually require a Pair, an interface is usually what they need. Here is an example:
interface Pair<L, R> {
public L getL();
public R getR();
}
So, when people want to return two values they can do the following:
... //Calcuate the return value
final Integer v1 = result1;
final String v2 = result2;
return new Pair<Integer, String>(){
Integer getL(){ return v1; }
String getR(){ return v2; }
}
This is a pretty lightweight solution, and it answers the question "What is the semantic of a Pair<L,R>?". The answer is, this is an interface build with two (may be different) types, and it has methods to return each of them. It is up to you to add further semantic to it. For example, if you are using Position and REALLY want to indicate it in you code, you can define PositionX and PositionY that contains Integer, to make up a Pair<PositionX,PositionY>. If JSR 308 is available, you may also use Pair<#PositionX Integer, #PositionY Ingeger> to simplify that.
EDIT:
One thing I should indicate here is that the above definition explicitly relates the type parameter name and the method name. This is an answer to those argues that a Pair is lack of semantic information. Actually, the method getL means "give me the element that correspond to the type of type parameter L", which do means something.
EDIT:
Here is a simple utility class that can make life easier:
class Pairs {
static <L,R> Pair<L,R> makePair(final L l, final R r){
return new Pair<L,R>(){
public L getL() { return l; }
public R getR() { return r; }
};
}
}
usage:
return Pairs.makePair(new Integer(100), "123");
JavaFX (which comes bundled with Java 8) has the Pair< A,B > class
As many others have already stated, it really depends on the use case if a Pair class is useful or not.
I think for a private helper function it is totally legitimate to use a Pair class if that makes your code more readable and is not worth the effort of creating yet another value class with all its boiler plate code.
On the other hand, if your abstraction level requires you to clearly document the semantics of the class that contains two objects or values, then you should write a class for it. Usually that's the case if the data is a business object.
As always, it requires skilled judgement.
For your second question I recommend the Pair class from the Apache Commons libraries. Those might be considered as extended standard libraries for Java:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
You might also want to have a look at Apache Commons' EqualsBuilder, HashCodeBuilder and ToStringBuilder which simplify writing value classes for your business objects.
You can use javafx utility class, Pair which serves the same purpose as pair <> in c++. https://docs.oracle.com/javafx/2/api/javafx/util/Pair.html
Collections.singletonMap(left, rigth);
another terse lombok implementation
import lombok.Value;
#Value(staticConstructor = "of")
public class Pair<F, S> {
private final F first;
private final S second;
}
Simple way Object [] - can be use as anу dimention tuple
Despite being syntactically similar, Java and C++ have very different paradigms. Writing C++ like Java is bad C++, and writing Java like C++ is bad Java.
With a reflection based IDE like Eclipse, writing the necessarily functionality of a "pair" class is quick and simple. Create class, define two fields, use the various "Generate XX" menu options to fill out the class in a matter of seconds. Maybe you'd have to type a "compareTo" real quick if you wanted the Comparable interface.
With separate declaration / definition options in the language C++ code generators aren't so good, so hand writing little utility classes is more time consuming tedium. Because the pair is a template, you don't have to pay for functions you don't use, and the typedef facility allows assigning meaningful typenames to the code, so the objections about "no semantics" don't really hold up.
Pair would be a good stuff, to be a basic construction unit for a complex generics, for instance, this is from my code:
WeakHashMap<Pair<String, String>, String> map = ...
It is just the same as Haskell's Tuple
For programming languages like Java, the alternate data structure used by most programmers to represent pair like data-structures are two array, and data is accessed via the same index
example: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
This isn't ideal as the data should be bound together, but also turn out to be pretty cheap. Also, if your use case demands storing co-ordinates then its better to build your own data structure.
I've something like this in my library
public class Pair<First,Second>{.. }
You can use Google's AutoValue library - https://github.com/google/auto/tree/master/value.
You create a very small abstract class and annotate it with #AutoValue and the annotation processor generates a concrete class for you that has a value semantic.
Here are some libraries that have multiple degrees of tuples for your convenience:
JavaTuples. Tuples from degree 1-10 is all it has.
JavaSlang. Tuples from degree 0-8 and lots of other functional goodies.
jOOλ. Tuples from degree 0-16 and some other functional goodies. (Disclaimer, I work for the maintainer company)
Functional Java. Tuples from degree 0-8 and lots of other functional goodies.
Other libraries have been mentioned to contain at least the Pair tuple.
Specifically, in the context of functional programming which makes use of a lot of structural typing, rather than nominal typing (as advocated in the accepted answer), those libraries and their tuples come in very handy.
Brian Goetz, Paul Sandoz and Stuart Marks explain why during QA session at Devoxx'14.
Having generic pair class in standard library will turn into technical debt once value types introduced.
See also: Does Java SE 8 have Pairs or Tuples?
I noticed all the Pair implementations being strewn around here attribute meaning to the order of the two values. When I think of a pair, I think of a combination of two items in which the order of the two is of no importance. Here's my implementation of an unordered pair, with hashCode and equals overrides to ensure the desired behaviour in collections. Also cloneable.
/**
* The class <code>Pair</code> models a container for two objects wherein the
* object order is of no consequence for equality and hashing. An example of
* using Pair would be as the return type for a method that needs to return two
* related objects. Another good use is as entries in a Set or keys in a Map
* when only the unordered combination of two objects is of interest.<p>
* The term "object" as being a one of a Pair can be loosely interpreted. A
* Pair may have one or two <code>null</code> entries as values. Both values
* may also be the same object.<p>
* Mind that the order of the type parameters T and U is of no importance. A
* Pair<T, U> can still return <code>true</code> for method <code>equals</code>
* called with a Pair<U, T> argument.<p>
* Instances of this class are immutable, but the provided values might not be.
* This means the consistency of equality checks and the hash code is only as
* strong as that of the value types.<p>
*/
public class Pair<T, U> implements Cloneable {
/**
* One of the two values, for the declared type T.
*/
private final T object1;
/**
* One of the two values, for the declared type U.
*/
private final U object2;
private final boolean object1Null;
private final boolean object2Null;
private final boolean dualNull;
/**
* Constructs a new <code>Pair<T, U></code> with T object1 and U object2 as
* its values. The order of the arguments is of no consequence. One or both of
* the values may be <code>null</code> and both values may be the same object.
*
* #param object1 T to serve as one value.
* #param object2 U to serve as the other value.
*/
public Pair(T object1, U object2) {
this.object1 = object1;
this.object2 = object2;
object1Null = object1 == null;
object2Null = object2 == null;
dualNull = object1Null && object2Null;
}
/**
* Gets the value of this Pair provided as the first argument in the constructor.
*
* #return a value of this Pair.
*/
public T getObject1() {
return object1;
}
/**
* Gets the value of this Pair provided as the second argument in the constructor.
*
* #return a value of this Pair.
*/
public U getObject2() {
return object2;
}
/**
* Returns a shallow copy of this Pair. The returned Pair is a new instance
* created with the same values as this Pair. The values themselves are not
* cloned.
*
* #return a clone of this Pair.
*/
#Override
public Pair<T, U> clone() {
return new Pair<T, U>(object1, object2);
}
/**
* Indicates whether some other object is "equal" to this one.
* This Pair is considered equal to the object if and only if
* <ul>
* <li>the Object argument is not null,
* <li>the Object argument has a runtime type Pair or a subclass,
* </ul>
* AND
* <ul>
* <li>the Object argument refers to this pair
* <li>OR this pair's values are both null and the other pair's values are both null
* <li>OR this pair has one null value and the other pair has one null value and
* the remaining non-null values of both pairs are equal
* <li>OR both pairs have no null values and have value tuples <v1, v2> of
* this pair and <o1, o2> of the other pair so that at least one of the
* following statements is true:
* <ul>
* <li>v1 equals o1 and v2 equals o2
* <li>v1 equals o2 and v2 equals o1
* </ul>
* </ul>
* In any other case (such as when this pair has two null parts but the other
* only one) this method returns false.<p>
* The type parameters that were used for the other pair are of no importance.
* A Pair<T, U> can return <code>true</code> for equality testing with
* a Pair<T, V> even if V is neither a super- nor subtype of U, should
* the the value equality checks be positive or the U and V type values
* are both <code>null</code>. Type erasure for parameter types at compile
* time means that type checks are delegated to calls of the <code>equals</code>
* methods on the values themselves.
*
* #param obj the reference object with which to compare.
* #return true if the object is a Pair equal to this one.
*/
#Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(this == obj)
return true;
if(!(obj instanceof Pair<?, ?>))
return false;
final Pair<?, ?> otherPair = (Pair<?, ?>)obj;
if(dualNull)
return otherPair.dualNull;
//After this we're sure at least one part in this is not null
if(otherPair.dualNull)
return false;
//After this we're sure at least one part in obj is not null
if(object1Null) {
if(otherPair.object1Null) //Yes: this and other both have non-null part2
return object2.equals(otherPair.object2);
else if(otherPair.object2Null) //Yes: this has non-null part2, other has non-null part1
return object2.equals(otherPair.object1);
else //Remaining case: other has no non-null parts
return false;
} else if(object2Null) {
if(otherPair.object2Null) //Yes: this and other both have non-null part1
return object1.equals(otherPair.object1);
else if(otherPair.object1Null) //Yes: this has non-null part1, other has non-null part2
return object1.equals(otherPair.object2);
else //Remaining case: other has no non-null parts
return false;
} else {
//Transitive and symmetric requirements of equals will make sure
//checking the following cases are sufficient
if(object1.equals(otherPair.object1))
return object2.equals(otherPair.object2);
else if(object1.equals(otherPair.object2))
return object2.equals(otherPair.object1);
else
return false;
}
}
/**
* Returns a hash code value for the pair. This is calculated as the sum
* of the hash codes for the two values, wherein a value that is <code>null</code>
* contributes 0 to the sum. This implementation adheres to the contract for
* <code>hashCode()</code> as specified for <code>Object()</code>. The returned
* value hash code consistently remain the same for multiple invocations
* during an execution of a Java application, unless at least one of the pair
* values has its hash code changed. That would imply information used for
* equals in the changed value(s) has also changed, which would carry that
* change onto this class' <code>equals</code> implementation.
*
* #return a hash code for this Pair.
*/
#Override
public int hashCode() {
int hashCode = object1Null ? 0 : object1.hashCode();
hashCode += (object2Null ? 0 : object2.hashCode());
return hashCode;
}
}
This implementation has been properly unit tested and the use in a Set and Map has been tried out.
Notice I'm not claiming to release this in the public domain. This is code I've just written for use in an application, so if you're going to use it, please refrain from making a direct copy and mess about with the comments and names a bit. Catch my drift?
If anyone wants a dead-simple and easy to use version I made my available at https://github.com/lfac-pt/Java-Pair. Also, improvements are very much welcome!
com.sun.tools.javac.util.Pair is an simple implementation of a pair.
It can be found in jdk1.7.0_51\lib\tools.jar.
Other than the org.apache.commons.lang3.tuple.Pair, it's not just an interface.
public class Pair<K, V> {
private final K element0;
private final V element1;
public static <K, V> Pair<K, V> createPair(K key, V value) {
return new Pair<K, V>(key, value);
}
public Pair(K element0, V element1) {
this.element0 = element0;
this.element1 = element1;
}
public K getElement0() {
return element0;
}
public V getElement1() {
return element1;
}
}
usage :
Pair<Integer, String> pair = Pair.createPair(1, "test");
pair.getElement0();
pair.getElement1();
Immutable, only a pair !

Categories