0

What is the elegant way to rewrite something like this

private boolean containsNulls(HashBasedTable table) {
    for(Object column : table.columnKeySet()) {
        for(Object row : table.rowKeySet()) {
            if(table.get(row, column) == null) {
                return true;
            }
        }
    }
    return false;
}

using Java 8 features?

I am looking for something like

tableCells.stream().filter(cell -> cell.getValue() == null)
       .findFirst().orElse(null);

(per Return from lambda forEach() in java) however having some trouble writing it as a nested loop.

Suggestions?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
9706437
  • 13
  • 3
  • 1
    I'm not sure what makes code "elegant" or not, but readability, simplicity, clarity, and correctness are all important. If you were to hand this code to someone with _less_ experience than you, would they be able to understand it, make changes to it, troubleshoot bugs, etc.? When writing code is your job, non-obvious code means you will – more likely than not – own that code/project forever, even if you're sick of it and want ot move on to something more interesting. I've seen this happen repeatedly to really smart engineers – stuck with screwball systems that everyone else is scared of. – Kaan Aug 04 '19 at 23:18
  • 1
    @kaan thank you for the comment. In this case by "elegant" I mean that I want my code reviewer to think I understand Java 8 features when in fact I do not. – 9706437 Aug 04 '19 at 23:24
  • 1
    Using Java 8 features everywhere you *can* but not where you *should* will not help you while code reviewing. Your current code is IMO easier to read than stream version provided by Eugene so I would stay with it, unless you would *need* to use stream version, lets say because of possible gain from parallel streams. – Pshemo Aug 04 '19 at 23:43
  • @Pshemo I _need_ to use stream version because my code reviewer will reject it and tell me to learn Java 8 otherwise. Jokes aside - I am really just curious if there are intelligent, elegant, simple ways of using these features which other people might suggest so that I might learn. – 9706437 Aug 05 '19 at 01:17

2 Answers2

2

you can you 2 nested anyMatch():

private boolean containsNulls(HashBasedTable table) {
    return table.columnKeySet()
        .stream()
        .anyMatch(column -> table.rowKeySet()
            .stream()
            .anyMatch(row -> table.get(row, column) == null)
        );
}
yelliver
  • 5,648
  • 5
  • 34
  • 65
1
 return table.columnKeySet()
             .stream()
             .flatMap(x -> table.rowKeySet().stream().map(y -> new Object[]{x,y}))
             .anyMatch(x -> table.get(x[1], x[0]) == null)

I did not compile this, so I hope did not miss a parentheses...

Just notice that you need the most recent java-8 there is to get this truly to be like your loop, read this for details.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Clever, but it doesn't work. Unfortunately the 'x's are type Object and the `y`, somehow, is not Object but ``. I'm not sure you would even be able to get a method `rowKeySet()` on the first Object x - even after typecasting it would be a String object from the columnKeySet, not a column of the table. Here we could instead use `.flatmap(x -> table.rowKeySet().stream` and so on. I think this is close – 9706437 Aug 04 '19 at 23:33
  • @9706437 seems like I missed something indeed, care to try now? – Eugene Aug 04 '19 at 23:48
  • the bit at the end - mapping to Object[] and assuming `.anyMatch(x` will be typed as Object[] - does not work. – 9706437 Aug 05 '19 at 01:40