Pierre Guilbert
Pierre Guilbert

Reputation: 5177

Is there clean syntax for checking if multiple variables all have the same value?

We have n variables X = {x1,x2,...xn} they are not in any structures whatsoever.

In python for example I can do that: if (x1 == x2 == x3 == xn):

In java I must do: if((x1 == x2) && (x2 == x3) && (x3 == xn)):

Do you know a simple way to improve this syntax? (Imagine very long variable name and lot of them)

Thanks.

Upvotes: 30

Views: 35341

Answers (13)

johanwannheden
johanwannheden

Reputation: 962

Using the following code snipped you can identify Map values with duplicates:

    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        int c = 1;
        int d = 3;

        Collection<Integer> collectionOfValues = List.of(a, b, c, d);

        Map<Integer, List<Integer>> groupedByUniqueKeys = collectionOfValues.stream()
            .collect(
                groupingBy(
                    Function.identity()));

        System.out.println(groupedByUniqueKeys);
        // {1=[1, 1], 2=[2], 3=[3]}
    }

The mapping for key 1 will contain values for the variables with equal values (a and c).

Upvotes: -2

kapex
kapex

Reputation: 29999

In Java 8 this can be done as a one-liner using a Stream:

boolean allEqual = Stream.of(x1, x2, x3, x4).distinct().count() == 1;

Basically distinct filters the stream by checking each element for equality, so that only unique elements remain. If there is exactly one element left after filtering, it means all original elements are equal.

Upvotes: 1

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

Just to bring these answers up to date (Java SE 9).

 Set.of(x1,x2,...xn).size() == 1

Makes perfect sense to a mathematician. (I am calling myself a mathematician in this context.)

(Obviously, there are boxing overheads of one sort of another for the Integers, Integer[], Set and, potentially, internally to the Set.)

Edit: Stuart Marks points out that Set.of throws IllegalArgumentException if there are duplicate elements. Alternative:

Set.copyOf(Arrays.asList(x1,x2,...xn)).size() == 1

or depending on your definition of clean:

copyOf(asList(x1,x2,...xn)).size() == 1

(Assumes excessive static imports.)

Upvotes: 0

Pavel
Pavel

Reputation: 2776

/*
* reference - basic String to compare against
* entries - all other objects for comparison
*/
public static boolean allEqual(String reference, String... entries) {
        return Arrays.stream(entries)
                .allMatch(entry -> Objects.equals(reference, entry));
}

/*
* Method can be generalized to use <T> instead of String
*/
public static <T>boolean allEqual(T reference, T... entries) {
    return Arrays.stream(entries)
            .allMatch(entry -> Objects.equals(reference, entry));
}

public static void main(String[] args) {
    System.out.println(allEqual("X", "X", "X", "X")); // true
    System.out.println(allEqual("X", "X", "Y"));      // false
    System.out.println(allEqual("X"));                // true

    System.out.println(allEqual(10, 10, 9));          // false
    System.out.println(allEqual(10, 10));             // true
    System.out.println(allEqual(10, new Integer[] {10, 10, 10})); // true
}

Upvotes: 2

Nikolai  Shevchenko
Nikolai Shevchenko

Reputation: 7531

org.apache.commons.lang3.BooleanUtils public static boolean and(final boolean... array)

Upvotes: 0

Robin Keskisarkka
Robin Keskisarkka

Reputation: 896

I like the boilerplate logic that has already been suggested, but typically any of the arguments in the list can be null, which could cause a NullPointerException to be thrown. We should therefore test for null first and use == to compare object references where appropriate:

public static boolean allEqual(Object key, Object... objs) {
    for(Object o : objs)
        if((key != null && !key.equals(o)) || key != o) return false;
    return true;
}

Upvotes: 0

Priidu Neemre
Priidu Neemre

Reputation: 3061

Another quick way to achieve this would be via the array -> List -> HashSet conversion route, as in:

Standard Java:

if(new HashSet<Object>(Arrays.asList(x1, x2, x3, x4, x5)).size() == 1) {

}

Google Guava:

if(Sets.newHashSet(Ints.asList(x1, x2, x3, x4, x5)).size() == 1) {

}

The aforementioned solution doesn't look too clean in it's own right, though, so it should definitely be isolated into a separate utility method with a sensible name (in which case you'd probably be better off with Peter Lawrey's or Jon Skeet's solution in the first place).

I'd also expect this approach to be associated with at least a tiny performance hit, since it's clear that multiple Collections have to be instantiated & populated.

So to reiterate - only use this solution if you are hell-bent on hitting a one-liner.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1502306

If you have lots of these variables, have you considered putting them in a collection instead of having them as separate variables? There are various options at that point.

If you find yourself doing this a lot, you might want to write helper methods, possibly using varargs syntax. For example:

public static boolean areAllEqual(int... values)
{
    if (values.length == 0)
    {
        return true; // Alternative below
    }
    int checkValue = values[0];
    for (int i = 1; i < values.length; i++)
    {
        if (values[i] != checkValue)
        {
            return false;
        }
    }
    return true;
}

An alternative as presented by glowcoder is to force there to be at least one value:

public static boolean areAllEqual(int checkValue, int... otherValues)
{
    for (int value : otherValues)
    {
        if (value != checkValue)
        {
            return false;
        }
    }
    return true;
}

In either case, use with:

if (HelperClass.areAllEqual(x1, x2, x3, x4, x5))
{
    ...
}

Upvotes: 30

Peter Lawrey
Peter Lawrey

Reputation: 533680

Similar to @Jon's solution but shorter.

public static boolean areAllTheSame(int value, int... values) {
    for (int i: values) if(value != i) return false;
    return true;
}

Upvotes: 8

ewan.chalmers
ewan.chalmers

Reputation: 16245

If you don't like typing, you could lose the nested paretheses:

if(x1 == x2 && x2 == x3 && x3 == xn);

Upvotes: 1

Jesper
Jesper

Reputation: 206916

You could write a method that makes this look less cumbersome:

boolean areAllEqual(Object... values) {
    if (values.length < 2) {
        return true;
    }

    for (int i = 1; i < values.length; i++) {
        if (!values[i].equals(values[0])) {
            return false;
        }
    }

    return true;
}

Use it like this:

if (areAllEqual(x1, x2, x3, x4, x5)) {
    // do something
}

edit Too slow...! :-(

Upvotes: 5

corsiKa
corsiKa

Reputation: 82589

You could create a utility method like this:

public boolean allEqual(Object... objs) {
    if(objs.length < 2) return true; // 0 or 1 objects are all equal
    Object key = objs[0]; // pick one
    for(Object o : objs) if(!o.equals(key)) return false;
    return true;
}

Another option would be

public boolean allEqual(Object key, Object... objs) {
    for(Object o : objs) if(!o.equals(key)) return false;
    return true;
}

To simplify a lot of boilerplate logic. Then just go

if(allEqual(x,x1,x2,x3))

Obviously the two are mutually exclusive (they are signaturely ambigous) but you could have allEqual and allEqualWithKey

Upvotes: 13

Pops
Pops

Reputation: 30848

Unfortunately, no, there's no syntactic sugar available. This is a common gripe about Java.

Upvotes: 2

Related Questions