{{announcement.body}}
{{announcement.title}}

A Stream Annoyance

DZone 's Guide to

A Stream Annoyance

A short but effective rant on one developer's irritation with how easy it is to read stream-processing, and gives you three examples to illustrate.

· Java Zone ·
Free Resource

Of course we all love the creamy, functional goodness that oozed from Java 8. And I'm certainly no imperativist, like those in this Java video.

But one thing bothers me.

It's minor. Hardly worth mentioning, barely an inconvenience. But...irritating.

It concerns me how easy it is to read stream-processing.

Let's yank a random Java repo from GitHub — Apache Flink — and take from it an example of a perfectly unobjectionable stream-processing. In  FlinkPreparingTableBase we find:

Java
 




x


 
1
for (Set<String> keys : uniqueKeys) {
2
    boolean allUniqueKeysExists = keys.stream()
3
        .allMatch(f -> rowType.getField(f, false, false) != null);
4
 
          
5
    ... 
6
}


(Code simplified for presentation purposes.) The question is: what is the type of parameter f?

And the answer is straightforward: it's a String. How do we know? Because the stream is processing over keys, and keys is a Set of String. All declared two lines before; an eye-flick away.

Fine. It might be a little surprising that the parameter is called f (for, "Field") rather than k (for, "Key") but fine.

Now let's look at another class, Flink's  PlannerQueryOperation:

Java
 




xxxxxxxxxx
1
11


 
1
public PlannerQueryOperation() {
2
    DataType[] fieldTypes = rowType.getFieldList()
3
        .stream()
4
        .map(field ->
5
             LogicalTypeDataTypeConverter.fromLogicalTypeToDataType(
6
             FlinkTypeFactory.toLogicalType(field.getType())))
7
        .toArray(DataType[]::new);
8
 
          
9
   ...
10
}
11
 
          


Now, similar question: what is the type of parameter field?

Firstly, at least the name's spelled out: "field," rather than, "f". But is it still a String?

Well, field is an element of whatever getFieldList() returns. And we note that variable  rowType  appears in both snippets (both of which turn out to be of type  RelDataType). In the first snippet, we call rowType.getField() with a String parameter, so maybe the second snippet's   rowType.getFieldList() also returns a collection of  String  that we can then stream-process?

But then we peek further into the stream and find  field.getType().

So whatever  field is, it ain't no String.

This is the problem.

We don't know the type of  field  and we can't see it with a casual flick of the eyes, as we did in the first example.

Instead, we have to go find  RelDataType and check what type  getFieldList() returns.

And all of this because our Glorious Java Overlords made it optional to explicitly specify parameter types in stream-processing.

This is what irks me.

Why didn't they make this mandatory?

We can remedy the problem by explicitly expressing the type, as in:

Java
 




xxxxxxxxxx
1
10


 
1
public PlannerQueryOperation() {
2
    DataType[] fieldTypes = rowType.getFieldList()
3
        .stream()
4
        .map((RelDataTypeField field) ->
5
             LogicalTypeDataTypeConverter.fromLogicalTypeToDataType(
6
             FlinkTypeFactory.toLogicalType(field.getType())))
7
        .toArray(DataType[]::new);
8
 
          
9
   ...
10
}


So: is this third snippet more, "Easy to read," than the second?

What do we mean by saying code is, "Easy to read?"

Some would say that the second is easier to read because it omits non-essential types and stinkin' boiler-plate brackets.

Some would say that the third is easier to read because it makes types explicit.

I know which I prefer.

I just wish the Java gods hadn't given us a choice.

Topics:
java, parameter declaration, parameter types, rant, stream, stream processing

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}