Stream processing of Java 8 can be omitted so far!

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.

Introduction

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.

Java 7 and earlier

First, let's write with legacy code before Java 7.

Use extended for statement

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.

Java 8 or later

From here, I'll write in modern Java 8 or later code.

Use Stream

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.

Omit the argument type name

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.

Omit the parentheses in the argument part

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.

Omit the curly braces in the processing section

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.

Shorten variable name

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.

Use method reference

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.

in conclusion

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.

Reference link

[^ 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

Stream processing of Java 8 can be omitted so far!
Basic processing flow of java Stream
[Java] Stream processing
[Java] Stream API --Stream termination processing
[Java] Stream API --Stream intermediate processing
Java Stream cannot be reused.
Summary of java error processing
Only the top level Stream can be parallelized with Java Stream.
About Lambda, Stream, LocalDate of Java8
Summary of ORM "uroboroSQL" that can be used in enterprise Java
Java file input / output processing that can be used through historical background
Data processing using stream API from Java 8
[Processing x Java] Construction of development environment
Things to be aware of when writing Java
[Java] Be aware of short circuits (short-circuit evaluation)
[Note] Java: Speed of List processing by purpose
[Java / Spring Boot] Spring security ⑤ --Implementation of logout processing
[Java] char type can be cast to int type
Java Servlet should be aware of multithreaded environment