2

I was wondering if there is a way to make the first two lines of the following code a one-liner in Java, so that object is declared, assigned and null checked in one line:

Object object;
if ((object = queue.poll()) != null) {
    // do something with object
}
7
  • 2
    what do you want to do in your second line? it is just a condition. for that, it needs to be a statement Commented Apr 19, 2022 at 17:52
  • 1
    Object object = queue.poll(); if (object != null) { whatever } - Java does not require line feeds Commented Apr 19, 2022 at 17:59
  • @reveance Do you need this variable to be accessible somewhere else in the code or not? Commented Apr 19, 2022 at 18:09
  • @AlexanderIvanchenko No, just in the scope of the if block Commented Apr 19, 2022 at 18:20
  • @user16320675 Or maybe simply allow declaration in the if statement. Is there a reason not to: if((Object object = queue.poll()) != null) { ... }? Commented Apr 19, 2022 at 18:24

4 Answers 4

3

If you don't mind having the scope of the object variable being confined to the code in the curly brackets, then you can do this:

for (Object object; (object = queue.poll()) != null;) {
    // do whatever with object
    break;
}

that one isn't too far off from the typical thing we do when reading a file, like this:

for (String line; (line = reader.readLine()) != null;) {
    // do something with line
}

or alternatively as suggested by rzwitserloot:

for (Object object = queue.poll; object != null; object = null)   {
 // do something with object
}  

that way it polls only once, and omitting a break in the body of the loop does no harm. Nulling out the object in the increment makes sure the loop terminates after the first pass.

It is kind of abusive having a for loop where you have no intention of looping. I would stay with the multi-line version you started with.

But if you are polling, usually you need a loop anyway.

Sign up to request clarification or add additional context in comments.

2 Comments

How about: for (Object object = queue.poll(); object != null; object = null) { /* do whatever (no break needed) */ }? Still dubious, but shorter and cleaner than abusing Optional, and it saves a line, I guess, vs your implementation.
I like the ingenuity, but I see this potentially causing confusion if people don't see the break, but definitely would like the first one as an alternative to a poll in a while loop that has a declaration above it. Thanks
2

May not too nice looking:

Optional.ofNullable(queue.poll())
    .ifPresent(object -> ... do something with object ...);

Or

Optional.ofNullable(queue.poll()).ifPresent(object -> {
    ... do something with object ...;
});

So you might have a better opinion of the straight:

Object object = queue.poll();
if (object != null) {
    // do something with object
}

5 Comments

this is what the OP asked for, didn't say it couldn't be ugly.,..
it is abusing Optional. mine is abusing for. not sure which is worse. :-|
My answer was triggered by the null safe Optional. However it still is a two-liner when the expression is placed on two lines. "Ugly" is relative here as Deque does only provide a nullable poll(). So Nathan is right w.r.t. to that.
Let's wait for an answer with try (new AutoCloseable ...) { - ;).
I like this one the most personally, even though it's not beautiful, it does do exactly what I want with the least amount of (needless imo) instructions from me
1

The condition is slightly contrived. Therefore, it's hard to meet the requirement without misusing something, like hiding a null-check with optional, which isn't intended for that purpose.

Actually, the following code will be both the most simple and expressive:

Object object = queue.poll()
if (object != null) {
    // do something with object
}

Elimination of a single line will have a cost - the readability of code.

The approach I came up with is to use Stream.ofNullable() which will produce an empty stream if the provided argument is null. Then turn the stream into an iterator and invoke forEachRemaining() on it. This method expects a Supplier, and you can define it on the spot by placing the logic from the if-statement, or separately.

Stream.ofNullable(queue.poll()).iterator().forEachRemaining(System.out::println);

Note: forEach() method defined by the Stream interface isn't used here deliberately in order to be aligned with the guidelines of the Stream API documentation in regard to side-effects. And an Iterator is being used instead because there's no such requirements for its method forEachRemaining().

Comments

0

Turn your poll() into a supplier and pretend you're working in a language that encourages monkey patching

Supplier<Optional<Object>> spout = () -> Optional.ofNullable(queue.poll());
spout.get().ifPresent(o -> System.out.println(o));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.