tags:

views:

135

answers:

5

I need help about this strange operator |=. Can you explain to me what this code does ?

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean result = false;
    for (E e : c) {
        result |= add(e);
    }
    return result;
}
+6  A: 

It is a shorthand for:

result = result | add(e);

Where the | is the bitwise OR operator.

Femaref
If you had to explain this to non-programmer. What it would be?
Does the non-programmer know what binary numbers and OR mean? If no, explain those first. If yes, then do the bitwise OR on the binary representations of the contents of result and the outcome of calling add(e) and store the answer in the result reference.
duffymo
Actually, it's logical OR because it's applied to the `boolean` type. Not that the net effect is any different though.
Donal Fellows
So if result is true and every invocation of add(e) returns true but one does not, final result is false?
@Donal: That's wrong. Boolean or (`||`) short circuits, logical or (`|`) does not. So in this case `add(e)` is always evaluated, regardless whether `result` is already true or not.
musiKk
@musiKk: It's logical OR because it is applied to the boolean type, but it's not a short-circuiting OR. (The short-circuiting type is always boolean, but that's a one-way implication.)
Donal Fellows
I think the correct name would be **eager logical OR operator**
Ishtar
A: 

It is a bitwise OR-ing of result and add(e) and assigning it back to result. Shorthand notation instead of writing result = result | add(e)

Sagar V
+2  A: 

it's shorthand for result = result | add(e). The pipe is the bitwise or operator.

Raoul Duke
A: 

The or-assign operator (|=) sets the variable on the LHS to the value it previously contained OR-ed with the result of evaluating the RHS. For boolean types (as in this example) it changes the variable to contain true when the value is true (and otherwise has no net effect). It does not short-circuit evaluate.

The overall effect of the method is to call the current object's add method for each element of the argument collection, and to return true if any of those calls to add return true (i.e., if anything actually got added, under reasonable assumptions about the meaning of the result of add…)

Donal Fellows
+1  A: 

The code is adding all members of a Collection using the add() method which returns a boolean, indicating if the add() succeeded or not. What the addAll method does is return true if any of the adds succeeded and false if all of them failed. (This does seems odd to me, since I'd only return true if all the adds were succesful, but I digress.)

So you could do it like this:

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean result = false;
    for (E e : c) {
        if (add(e)) {
           result = true;
        }
    }
    return result;
}

But that's a little verbose as you can act on the result variable more directly:

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean result = false;
    for (E e : c) {
        result = add(e) || result;
    }
    return result;
}

So we're logically OR-ing the old value of result with the return value of add to get the new value. (Note - we want result to be on the right hand side of the ||; this is because || "shortcircuits" and doesn't bother checking the right hand side of an || if the left side is true). So if add(e) and result were the other way around it would not evaluate the right hand side - i.e. not run the add() method - once result were true.)

Whoever wrote that method decide they wanted to be as terse as possible so they changed:

result = add(e) || result;

to:

result |= add(e);

which is the same as:

result = result | add(e);

The | operator is a bitwise OR which is not the same a logical OR, except for booleans where the effect is basically the same, the only difference being the | does not have the shortcircuit behaviour mentioned above.

There is no ||= syntax in Java which is why the bitwise OR is being used, although even if it did it would probably have the same shortcircuit problem mentioned above.

Dave Webb
With a short-circuiting version, you'd expect no further adds to be done after one returns true, which would be surprising given the implied contract of the method name…
Donal Fellows
Brilliant, thanx!
@Donal Fellows - good point about the shortcircuiting of `||`. Have changed the answer to reflect this.
Dave Webb
FWIW: I've had a professor in University that would kill you if you did anything like: if (add(e)) { result = true; } :-)
Roalt
I would do the same Roalt.
Femaref