Idiomatic way to ensure many values are equal - java

Say I have a list of many primitive variables:
final int a = 3;
final int b = 4;
final int c = 4;
final int d = 4;
final int e = 4;
What's an idiomatic way to make sure they all hold the same value? The obvious way is simply
if (a == b && a == c && a == d && a == e) // ...
But I think this is error prone and hard to read, especially when the variables have proper names, unlike my example.
if ( numCategories == numTypes && numCategories == numColours
&& numCategories == numStyles && numCategories == numPrices) // ...
It would be nice if we could do the comparison like this:
if (a == b == c == d == e)
but obviously a == b resolves to a boolean so we can't compare that to c.
Is there a library function in the JDK or another utility library with maybe a signature somewhat like this?
static boolean areEqual(int... numbers)
then we could use it like so:
if (areEqual(a, b, c, d, e)) //...
I could easily write a function like this myself, but why reinvent the wheel if you don't have to?
Maybe there's another idiomatic way to accomplish this that I'm missing.

Using Streams, you can take advantage of some convenient methods to achieve your goal.
You can use Stream's or IntStream's distinct() combined with count() to find the number of unique elements:
For int variables:
if (IntStream.of(a,b,c,d,e).distinct().count() == 1) {
}
For reference type variables:
if (Stream.of(a,b,c,d,e).distinct().count() == 1) {
}
Another way, which is probably less efficient (but I'll keep it here since it's the first thing I thought about) is creating a Stream of all the elements you want to compare and then collecting them into a Set and checking the size of the Set is 1 (since Set doesn't allow duplicates) :
if (IntStream.of(a,b,c,d,e).boxed().collect(Collectors.toSet()).size() == 1) {
}
or
if (Stream.of(a,b,c,d,e).collect(Collectors.toSet()).size() == 1) {
}
for general Objects.

A naive option is to build methods that receives all the variables as varargs and compare them one after other. If one of them is different you will get false
public static boolean areEqual(int...nums)
{
for (int i = 0 ; i < nums.length - 1 ; ++i) {
if (nums[i] != nums[i + 1]) {
return false;
}
}
return true;
}
Uses
if (areEqual(a, b, c, d, e))

I like this approach. There's no auto-boxing and no magic numbers.
As per the documentation, it's also short-circuiting so therefore potentially more efficient than other methods. More importantly, it's very easy to read.
IntStream.of(a, b, c, d).allMatch(x -> x == e);
Credit to saka1029.

Related

Minifying Or/And expressions in Java?

I've always been curious if it's possible to simplify an Or expression Java. Example:
int mapVal = occurrenceMap.get(node.nextNode.nodeVal);
if (mapVal != null || mapVal != 5 )
versus...
if (occurrenceMap.get(node.nextNode.nodeVal) != ( null || 1) )
IMO, the second is more readable, but wondering if the language supports something like this.
Use getOrDefault
occurrenceMap.getOrDefault(node.nextNode.nodeVal, 5) != 5
if (occurrenceMap.get(node.nextNode.nodeVal) != ( null || 1) )
the second is more readable, but wondering if the language supports
something like this.
No Java not support that.
For a good solution I would like to use :
Integer i = occurrenceMap.get(node.nextNode.nodeVal);
if (i != null || i != 1)
Note : as Tim Biegeleisen mention in comment primitive int or type in general can't be null in Java.
First, int cannot be null. You don't need to check against null if you have an int. It just cannot happen.
Here is a method that checks whether a value is equal to any of a list of values:
public static <T> boolean anyEquals(T value, T... values) {
for (T val: values) {
if (val == value) { // or val.equals(value)
return true;
}
}
return false;
// implementation with streams
// return Arrays.stream(values).anyMatch(x -> x == value); // or x.equals(value)
}
Usage (supposing you are using Integers instead of int):
Integer i = ...;
boolean b = anyEquals(i, 5, 10, 15);
If you're into simplifying boolean expressions you should learn about some axioms and laws:
!!a = a
(!a || a) = true
(!a && a) = false
(true && a) = a
(false && a) = false
(true || a) = true
(false || a) = a
(!a || !b) = !(a && b)
(!a && !b) = !(a || b)
(a != b) = !(a == b)
(a <= b) = (b > a)
(a >= b) = (b < a)
The second one you've mentioned can't possibly be used in
Java because (a || b) already has a meaning so a == (c || d) already has a fixed meaning and changing this would probably break a lot of code. There might be languages that support such notations but they'll use a different operator instead of the binary boolean operator because otherwise it'd be impossible to distinguish what the programmer actually wants.
You could absolutely add such a feature to Java but you'd have to create a new operator to do this. But as of now: Java doesn't have this, and most languages don't.
Some languages allow you to do things like "a < b < c" which not all languages support (you'll have to write "a < b AND b < c").
You technically can create helper functions for this such as
"if isOneOf(mapVal, a, b)" but probably this is not going to be used widespread (most importantly because it'd require some runtime trickery to do this).

Can (a==1 && a==2 && a==3) evaluate to true in Java?

We know it can in JavaScript.
But is it possible to print "Success" message on the condition given below in Java?
if (a==1 && a==2 && a==3) {
System.out.println("Success");
}
Someone suggested:
int _a = 1;
int a = 2;
int a_ = 3;
if (_a == 1 && a == 2 && a_ == 3) {
System.out.println("Success");
}
But by doing this we are changing the actual variable. Is there any other way?
Yes, it's quite easy to achieve this with multiple threads, if you declare variable a as volatile.
One thread constantly changes variable a from 1 to 3, and another thread constantly tests that a == 1 && a == 2 && a == 3. It happens often enough to have a continuous stream of "Success" printed on the console.
(Note if you add an else {System.out.println("Failure");} clause, you'll see that the test fails far more often than it succeeds.)
In practice, it also works without declaring a as volatile, but only 21 times on my MacBook. Without volatile, the compiler or HotSpot is allowed to cache a or replace the if statement with if (false). Most likely, HotSpot kicks in after a while and compiles it to assembly instructions that do cache the value of a. With volatile, it keeps printing "Success" forever.
public class VolatileRace {
private volatile int a;
public void start() {
new Thread(this::test).start();
new Thread(this::change).start();
}
public void test() {
while (true) {
if (a == 1 && a == 2 && a == 3) {
System.out.println("Success");
}
}
}
public void change() {
while (true) {
for (int i = 1; i < 4; i++) {
a = i;
}
}
}
public static void main(String[] args) {
new VolatileRace().start();
}
}
Using concepts (and code) from a brilliant code golf answer, Integer values can be messed with.
In this case, it can make ints casted to Integers be equal when they wouldn't normally be:
import java.lang.reflect.Field;
public class Test
{
public static void main(String[] args) throws Exception
{
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
// array[129] is 1
array[130] = array[129]; // Set 2 to be 1
array[131] = array[129]; // Set 3 to be 1
Integer a = 1;
if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3)
System.out.println("Success");
}
}
Unfortunately it's not quite as elegant as Erwin Bolwidt's multithreaded answer (as this one requires Integer casting), but still some fun shenanigans take place.
In this question #aioobe suggests (and advise against) the use of C preprocessor for Java classes.
Although it is extremely cheaty, that's my solution:
#define a evil++
public class Main {
public static void main(String[] args) {
int evil = 1;
if (a==1 && a==2 && a==3)
System.out.println("Success");
}
}
If executed using the following commands it will output exactly one Success:
cpp -P src/Main.java Main.java && javac Main.java && java Main
As we already know that it is possible to make this code evaluate to true thanks to great answers of Erwin Bolwidt and phflack, I wanted to show that you need to keep a high level of attention when dealing with a condition that looks like the one presented in the question, as sometimes what you see might not be exactly what you think it is.
This is my attempt to show that this code prints Success! to the console. I know I cheated a bit, but I still think this is a good place to present it right here.
No matter what the purposes of writing code like this are - better to know how to deal with the following situation and how to check if you're not wrong with what you think you see.
I used the Cyrillic 'a' which is a distinct character from the latin 'a'. You can inspect the characters used in the if statement here.
This works because the names of the variables are taken from different alphabets. They are distinct identifiers, creating two distinct variables with a different value in each.
Note that if you want this code to work properly, character encoding needs to be changed to one supporting both characters, e.g. all Unicode encodings (UTF-8, UTF-16 (in BE or LE), UTF-32, even UTF-7), or Windows-1251, ISO 8859-5, KOI8-R (thank you - Thomas Weller and Paŭlo Ebermann - for pointing it out):
public class A {
public static void main(String[] args) {
int а = 0;
int a = 1;
if(а == 0 && a == 1) {
System.out.println("Success!");
}
}
}
(I hope you will never have to deal with that sort of problem any time in the future.)
There is another way to approach this (in additional to the volatile data-racing approach that I posted earlier), using the power of PowerMock. PowerMock allows methods to be replaced with other implementations. When that is combined with auto-unboxing, the original expression (a == 1 && a == 2 && a == 3), without modification, can be made true.
#phflack's answer relies on modifying the auto-boxing process in Java that uses the Integer.valueOf(...) call. The below approach relies on modifying auto-unboxing by changed the Integer.intValue() call.
The advantage of the below approach is that the original if-statement given by the OP in the question is used unchanged, which I think is the most elegant.
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.replace;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#PrepareForTest(Integer.class)
#RunWith(PowerMockRunner.class)
public class Ais123 {
#Before
public void before() {
// "value" is just a place to store an incrementing integer
AtomicInteger value = new AtomicInteger(1);
replace(method(Integer.class, "intValue"))
.with((proxy, method, args) -> value.getAndIncrement());
}
#Test
public void test() {
Integer a = 1;
if (a == 1 && a == 2 && a == 3) {
System.out.println("Success");
} else {
Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue());
}
}
}
Since this seems to be a follow-up of this JavaScript question, it’s worth noting that this trick and similar works in Java too:
public class Q48383521 {
public static void main(String[] args) {
int aᅠ = 1;
int ᅠ2 = 3;
int a = 3;
if(aᅠ==1 && a==ᅠ2 && a==3) {
System.out.println("success");
}
}
}
On Ideone
But note that this isn’t the worst thing you could do with Unicode. Using white-space or control characters that are valid identifiers parts or using different letters that look the same still creates identifiers that are different and can be spotted, e.g. when doing a text search.
But this program
public class Q48383521 {
public static void main(String[] args) {
int ä = 1;
int ä = 2;
if(ä == 1 && ä == 2) {
System.out.println("success");
}
}
}
uses two identifiers that are the same, at least from the Unicode point of view. They just use different ways to encode the same character ä, using U+00E4 and U+0061 U+0308.
On Ideone
So depending on the tool you’re using, they may not only look the same, Unicode enabled text tools may not even report any difference, always finding both when searching. You may even have the problem that the different representations get lost when copying the source code to someone else, perhaps trying to get help for the “weird behavior”, making it non-reproducible for the helper.
Inspired by the #Erwin's excellent answer, I wrote a similar example, but using Java Stream API.
And an interesting thing is that my solution works, but in very rare cases (because just-in-time compiler optimizes such a code).
The trick is to disable any JIT optimizations using the following VM option:
-Djava.compiler=NONE
In this situation, the number of success cases increases significantly. Here is the code:
class Race {
private static int a;
public static void main(String[] args) {
IntStream.range(0, 100_000).parallel().forEach(i -> {
a = 1;
a = 2;
a = 3;
testValue();
});
}
private static void testValue() {
if (a == 1 && a == 2 && a == 3) {
System.out.println("Success");
}
}
}
P.S. Parallel streams use ForkJoinPool under the hood, and variable a is shared between multiple threads without any synchronization, that's why the result is non-deterministic.
Along similar lines, by forcing a float (or double) to underflow (or overflow) through division (or multiplication) by a large number:
int a = 1;
if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY
&& a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY
&& a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) {
System.out.println("Success");
}

why if comparison doesn't work in java

I am making a Hash Table in java.
In searching function, I am doing some comparison in IF statement. but it is not doing any comparison.
here's is some part of my code.
while (table[pos]!=null) {
if (table[pos]==key) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
}
else {pos=h(home+p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");
return;
}
It doesn't work even when table[pos] and key are the same!
but I add very simple assigning variable to another one. It work! I don't know why it works. I wanna know it xD
while (table[pos]!=null) {
int x = table[pos];
if (x==key) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
}
else {pos=h(home+p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");
return;
}
Well, if table[pos] and key are both Integer (and table[pos] must be a reference type, since you are comparing it to null in the while statement), they should be compared with equals, not with ==, since two different Integer objects may have the same int value.
When you assign table[pos] to the int variable x, it is un-boxed to a primitive value.
Now, when you compare the int x to the Integer key, the key is also un-boxed to an int, and int comparison works with ==.
This can be demonstrated by the following short example:
Integer i1 = 300;
Integer i2 = 300;
System.out.println (i1 == i2);
int i3 = i1;
System.out.println (i3 == i2);
which outputs:
false
true
The code code would be:
while (table[pos] != null) {
if (table[pos].equals(key)) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
} else {
pos = h(home + p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");
When comparing two objects with ==, you check if both of these references point to the same place in the memory, while using == with primitives simply checks if values are the same. To correctly check equation of values inside two Integers you should use equals() method.
In your second example you used unboxing from Integer to int so it checked values as you expected it to do. In the first one you compared if both values point to the same place in memory.
Actually the correct way is to use both just like HashMap does for example, this way we will always be sure. This is for example how HashMap does it internally:
if(((k = first.key) == key || (key != null && key.equals(k)))) ...
So in your case it would be:
if ((table[pos] == key) || (key != null && (table[pos].equals(key)))) {

Are there situations where if statements are irreplaceable by jump tables?

I did not went too deep into this idea, but i wonder if if statements can be replaced by jump tables.
If we have a set of ifs like
if(x = 0)
{
...
}
if(x = 1)
{
...
}
if(x = 2)
{
...
}
We could simply jump, direcly, to the routine that pertains to the value of x, if we had a table with pointers for each routine.
In other situations like user input, let's assume we read a character from stdin, we
would have like
if(c = 'a')
{
...
}
if(c = 'b')
{
...
}
We could also find a way to índex a jump table based on the value of c
My question is, in which situations is it TOTALLY impossible to replace an if by a jump table? Can computation be performed without if statements (or equivalents)
Jump tables are limited to situations when you check equality. They are less appropriate when you need to use non-equality checks, and also for if statements with OR conditions.
Of course you could always use a degenerate jump table on a single boolean condition, like this:
boolean condition = a > b && c < d || e != f;
switch (condition) {
case true: ... break;
case false: ... break;
}
However, this does not offer any advantage over a straightforward conditional.

how can i get true logic condition to true in java

That's my while loop, and the question is, how can i get a true condition?
s and t are Integer variables
while (s<=t && s>=t && s!=t )
EDIT
tl;dr the original question stated:
s and t are int variables (and OP commented they are not Integer variables)
Never!
s and t are int variables, so when s == t the third operand will fail, when s != t one of the first two operands will fail.
Possible, but unlikely, if they are declared as volatile int s, t; in a multi-threaded application.
EDIT
Question has been modified. Now s and t are Integer variables, which makes the answers referring to Integer objects more relevant.
By boxing the primitive value in an object:
Integer s = new Integer(5);
Integer t = new Integer(5);
boolean rslt = (s <= t && s >= t && s != t);
System.out.println("Result = " + rslt);
The rslt boolean here will indeed evaluate to true.
However, the following would return false:
s <= t && s >= t && !s.equals(t)
it is because in Java, for objects, == means that it is indeed the same instance, while equals is left up to be implemented by every class and typically means that the core values of the compared objects are the same -- while not necessarily being the same class instance (AKA object). The > and < for boxed primitives are evaluated agaist the primitive value, however == is checking the object identity.
It actually is possible:
public class EqualsTest
{
public static void main(String[] args)
{
Integer x = new Integer(Integer.parseInt(args[0]));
Integer y = new Integer(Integer.parseInt(args[1]));
if(x <= y && y <= x && y !=x)
{
System.out.println("equal");
}
else
{
System.out.println("not equal");
}
}
}
Compiling this and running it with two equal integer arguments produces:
$ java EqualsTest 5 5
equal
The reason that this works is due to autoboxing and the fact that, for objects, == only checks whether or not the references are the same (which, in the case above, they are not).
Never man, no way.
s<=t && s>=t returns true if s == t, and s == t && s != t returns false forever.
You cant the only way first two conditions result true is when s is equal to t and the third conditions negates this fact.
Hence i dont think its possible
If the two values are accessible by multiple threads (either static, or members variables of an object shared between multiple threads), you could do this:
Thread 1:
s = 1; // 1
t = 1; // 2
t = 2; // 5
Thread 2:
This is equivalent to your expression but easier to label.
boolean result = s <= t; // 3
if(result) {
result = s >= t; // 4
}
if(result) {
result = s != t; // 6
}
Assuming everything happens in the order given by the commented numbers, then at the end of thread 2's code, result will be true.
So, thread 1 sets s and t to be equal, then thread 2 checks that they're equal, then thread 1 sets them to be not equal, then thread 2 checks that they're not equal.
There are more complicated situations where this could be true, but this is the simplest one I could think of.

Categories

Resources