简体   繁体   中英

How can I clean up my Java Streams?

I have this stream, as well as quite a few others, where I abuse a bunch of calls to get the job done. Seems like an anti-pattern when taking advantage of J8.

+    Arrays.stream(resources)
+        .map(this::ingestFromFile)
+        .collect(Collectors.toList())
+        .stream()
+        .map(Container.class::cast)
+        .map(Container::getAll)
+        .flatMap(Collection::stream)
+        .collect(Collectors.toList())
+        .forEach(
+            dataType -> {
+              loaderConstants.getRepo(dataType.toString()).save(dataType);
+              LOGGER.log(Level.INFO, "Saved: " + dataType);
+            });

How can I shorten this up and what pitfalls should I look out for in the future to avoid this type of development?

Well, you don't need the intermediate .collect(Collectors.toList()) calls as it's unnecessary and causes avoidable overhead.

Arrays.stream(resources)
     .map(this::ingestFromFile)
     .map(Container.class::cast)
     .map(Container::getAll)
     .flatMap(Collection::stream)
     .forEach(
            dataType -> {
              loaderConstants.getRepo(dataType.toString()).save(dataType);
              LOGGER.log(Level.INFO, "Saved: " + dataType);
     });

Then you can extract the body of the forEach to a method to simplify the pipeline.

My name is Andy, and I don't like streams.

And this code is a great example of why. (OK, they are sometimes helpful; but really only in very simple cases).

One thing that you (hopefully) learn very early on in programming is that identation makes your code readable: it helps you understand where things happen on related values.

In streamy code, indentation goes right out of the window. That left-hand margin is straight - see how all the periods line up:

+    Arrays.stream(resources)
+        .map(this::ingestFromFile)
+        .collect(Collectors.toList())
+        .stream()
+        .map(Container.class::cast)
+        .map(Container::getAll)
+        .flatMap(Collection::stream)
+        .collect(Collectors.toList())
+        .forEach(
+            dataType -> {
+              loaderConstants.getRepo(dataType.toString()).save(dataType);
+              LOGGER.log(Level.INFO, "Saved: " + dataType);
+            });

There is just no visual structure to it.

Especially as this is using forEach , it would just be easier to use loops.

for (var resource : resources) {
  var fromFile = resource.ingestFromFile();
  var container = (Container) fromFile;
  for (var dataType : container.getAll()) {
    loaderConstants.getRepo(dataType.toString()).save(dataType);
    LOGGER.log(Level.INFO, "Saved: " + dataType);
  }
}

(You may not be using Java 10; but I don't know the data types anyway. Fill in type types instead of var if you need it).

Personally, I think that is way easier to read. And it's shorter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM