As you know, ** Stream ** added in Java 8 makes it possible to write functional language-like processing in Java as well (more than 3 years have passed since the release in 2014 at the time of writing the article). It's a long time ago, but ...). [^ 1]
Since there is a mechanism to write code concisely, there is no reason not to use it.
Here, we will gradually omit the code that performs the simple process of converting List <String>
to List <Integer>
, and show the difference.
The following terms are assumed to be already understood and are not explained here.
If you want a quick understanding, the following articles are recommended.
First, let's write with legacy code before Java 7.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = new ArrayList<>();
for(final String numText : numTextList){
if(numText == null){
continue;
}
final int num = Integer.parseInt(numText);
numList.add(num);
}
Processing unit: 8 lines / 149 characters
The extended for statement is more modern than the regular for statement, but it's not cool to have to write the element type.
It is also dangerous that numList
is initialized with an empty list and that it has side effects on external variables during iterative processing.
From here, I'll write in modern Java 8 or later code.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter((String numText) -> {
return Objects.nonNull(numText);
})
.map((String numText) -> {
return Integer.parseInt(numText);
})
.collect(Collectors.toList());
Processing unit: 8 lines / 197 characters
By using Stream, you can now create numList
directly.
However, this is a fairly verbose writing style, and it cannot be said that it makes the best use of the goodness of Stream.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter((numText) -> {
return Objects.nonNull(numText);
})
.map((numText) -> {
return Integer.parseInt(numText);
})
.collect(Collectors.toList());
Processing unit: 8 lines / 183 characters
In lambda expressions, you can omit type names that can be inferred by type inference.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter(numText -> {
return Objects.nonNull(numText);
})
.map(numText -> {
return Integer.parseInt(numText);
})
.collect(Collectors.toList());
Processing unit: 8 lines / 179 characters
In a lambda expression, you can omit the parentheses surrounding the argument when there is one argument.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter(numText -> Objects.nonNull(numText))
.map(numText -> Integer.parseInt(numText))
.collect(Collectors.toList());
Processing unit: 4 lines / 145 characters
In a lambda expression, you can omit the curly braces and the return statement if the processor can write on one line. Only when I came here, I had fewer characters than Java 7 and earlier. If you write each process on one line, the connection of the method chain is easy to understand.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter(s -> Objects.nonNull(s))
.map(s -> Integer.parseInt(s))
.collect(Collectors.toList());
Processing unit: 4 lines / 121 characters
Since lambda expression variables are used only on the fly, variable names may be represented by a single character. In that case, it will be easier to understand if you use the first letter of the type name or the first letter of the original variable name. I think this format is a familiar writing style, but it's still optional.
final List<String> numTextList = Arrays.asList("0", "1", null);
final List<Integer> numList = numTextList.stream()
.filter(Objects::nonNull)
.map(Integer::parseInt)
.collect(Collectors.toList());
Processing unit: 4 lines / 107 characters
If the argument signatures (types and their order) match, you can use method references instead of lambda expressions. I think the simplification of the code has made the process flow clearer.
If you omit it too much, it may be difficult to understand.
In my case, I basically write it as a lambda expression, but when the method reference is useful (such as ʻObjects :: nonNull or
Path :: toFile`), I use it.
In any case, you want to write code that is highly readable.
[^ 1]: [New API and extension API that uses lambda expressions and streams in Java SE 8](http://docs.oracle.com/javase/jp/8/docs/technotes/guides/language/lambda_api_jdk8 .html)
Recommended Posts