23

I just going through code someone has written and I saw |= usage, looking up on Java operators, it suggests bitwise or and assign operation, can anyone explain and give me an example of it?

Here is the code that read it:

    for (String search : textSearch.getValue())
         matches |= field.contains(search);
Chris Chambers
  • 1,367
  • 21
  • 39
Rachel
  • 100,387
  • 116
  • 269
  • 365

6 Answers6

32
a |= b;

is the same as

a = (a | b);

It calculates the bitwise OR of the two operands, and assigns the result to the left operand.

To explain your example code:

for (String search : textSearch.getValue())
    matches |= field.contains(search);

I presume matches is a boolean; this means that the bitwise operators behave the same as logical operators.

On each iteration of the loop, it ORs the current value of matches with whatever is returned from field.contains(). This has the effect of setting it to true if it was already true, or if field.contains() returns true.

So, it calculates if any of the calls to field.contains(), throughout the entire loop, has returned true.

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • can you put in some values for a and b? – Rachel Apr 13 '12 at 13:51
  • oh ok, now it make some sense – Rachel Apr 13 '12 at 13:57
  • "this means that the bitwise operators behave the same as logical operators". Actually, logical operators will short-circuit. Short circuiting is probably desired here. – smp7d Apr 13 '12 at 14:13
  • 3
    It should also be noted that if `contains()` has no side-effects, this is rather inefficient. Adding at least an `if (matches) { break; }` inside the loop would be so much nicer... (Although I suppose `getValue()` may be returning so few searches that it won't make a noticeable difference...) – Izkata Apr 13 '12 at 18:03
13

a |= b is the same as a = (a | b)

Boolean Variables

In a boolean context, it means:

if (b) {
    a = true;
}

that is, if b is true then a will be true, otherwise a will be unmodified.

Bitwise Operations

In a bit wise context it means that every binary bit that's set in b will become set in a. Bits that are clear in b will be unmodified in a.

So if bit 0 is set in b, it'll also become set in a, per the example below:

  • This will set the bottom bit of an integer:

    a |= 0x01

  • This will clear the bottom bit:

    a &= ~0x01

  • This will toggle the bottom bit:

    a ^= 0x01;

Alnitak
  • 334,560
  • 70
  • 407
  • 495
3

This code:

int i = 5;
i |= 10;

is equivalent to this code:

int i = 5;
i = i | 10;

Similarly, this code:

boolean b = false;
b |= true;

is equivalent to this one:

boolean b = false;
b = b | true;

In the first example, a bit-wise OR is being performed. In the second example, a boolean OR is performed.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
2

a |= b is the same as a = a | b

a | b is a bitwise operator if both operands are integral types (int, short, etc...). If both operands are booleans, then its is a boolean or.

When both a and b are booleans, the difference between a | b and a || b is that in the first, both sides are always evaluated, in the later b is only evaluated if a is false. It is sort of a "shortcut" operator.

This is useful for situations like this:

if (a == null || a.equals(b)) { .. do something .. } // works

if (a == null | a.equals(b)) { .. do something .. } // NPE if a is null

On the other hand, || actually is implemented as another conditional jump in the bytecode/machine-code. In some cases, it may be faster to evaluate boolean conditions using the | operator to avoid the additional jump (and thus branch predition, etc...). Definitely something for low-level micro-benchmarking to figure out which is better (and usually not important in most applications).

When you do a |= b you are always evaluating both a and b. It doesn't really make sense to have an a ||= b operators, since the equivalent a = a || b would translate to:

if (a) a = true;
else if (b) a = true
else a = false;

...due to the conditional nature of || evaluation. In other words, b would not be evaluated if a was already true.

ɲeuroburɳ
  • 6,990
  • 3
  • 24
  • 22
1

Could it be possible that the code has a bug and it was meant

matches = matches || field.contains(search);

so that matches should be true if at least one field contains the search variable?

adranale
  • 2,835
  • 1
  • 21
  • 39
  • 2
    your code is not functionally the same - if `matches` is already true then the short circuit operator will prevent evaluation of `field.contains(search)`. AFAIK the `|=` operator won't do that. – Alnitak Apr 13 '12 at 14:05
  • Which means my code is optimization of the original code – adranale Apr 13 '12 at 14:06
  • 1
    only if it's truly intended that `.contains()` is not called in those circumstances. – Alnitak Apr 13 '12 at 14:07
  • 1
    you mean if the `.contains()` method does not have side-effects – adranale Apr 13 '12 at 14:14
  • 1
    yeah, mostly - in this case it probably doesn't matter, but it's worth knowing that for boolean variables `a |= func()` is the same as `a = a | func()` which is not functionally the same as `a = a || func()`, even though the end result on `a` is the same. – Alnitak Apr 13 '12 at 16:26
0

That code snippet is a poor example of when to use that operator. Honestly I can't think of a great example of when to use this operator, but here's my best attempt:

boolean somethingIsTrue = testSomethingTrue();
if(somethingIsTrue){
    //Do something
}
somethingIsTrue |= testSomethingElseTrue();
if(somethingIsTrue){
    //Do something else
}
somethingIsTrue |= testSomethingElseTrue2();
if(somethingIsTrue){
    //Do something else than something or something else
}   

Note: You need 3 ifs because otherwise you could just do somethingIsTrue | testSomethingElseTrue() for the second if.


In case you were wondering why you shouldn't use the operator in the first example, here's why:

From a performance standpoint, it is poor because it does a compare and an assign for each loop instead of just a compare. Also, it continues iterating even when future iterations will have no effect (once matches gets set to true it will not change, and String.contains has no side effects).

It is also poor from a readability standpoint, based solely on the existence of this question ;)

Thus, in place of that snippet I'd go for:

for (String search : textSearch.getValue()){
    if(field.contains(search)){
        matches = true;
        break;
    }
}

On a side note, it seems to me like the original coder might have been playing a bit too much code-golf when (s)he wrote this :)

Community
  • 1
  • 1
Briguy37
  • 8,342
  • 3
  • 33
  • 53
  • There are many good use cases for this operator. Imagine methods like `addAll` or `removeAll` in a set, provided that you iterate over the collection in parameter. You `add` or `remove` in a loop, and you want to return `true` if you actually added or removed at least one entry. – Vlasec Nov 24 '19 at 21:45