Skip to content

Commit

Permalink
Updating script
Browse files Browse the repository at this point in the history
  • Loading branch information
wkorando committed Jul 24, 2021
1 parent fb17527 commit 34767c4
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 17 deletions.
6 changes: 3 additions & 3 deletions 012-read-file-improvements/FileReaderIII.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
```java
lines.skip(titleLine) //
.map(s -> s.split(",")).takeWhile(filterToCurrentMonth)//
List<ElectricProject> projects = lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
.values().stream().map(Optional::get).forEach(printResults);
.values().stream().map(Optional::get).toList();
```
2 changes: 1 addition & 1 deletion 012-read-file-improvements/FileReaderIV.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
```java
lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.map(s -> s.split(",")).takeWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
Expand Down
8 changes: 8 additions & 0 deletions 012-read-file-improvements/FileReaderV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```java
lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
.values().stream().map(Optional::get).forEach(printResults);
```
17 changes: 16 additions & 1 deletion 012-read-file-improvements/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public record ElectricProject(LocalDate reportingPeriod, String projectNumber, S

## Imperative Data Processing

In this imagined example, the goal of processing the retrieved data file is to find the highest producing solar project in every city.

Accomplishing this relatively simple task imperatively might look like below, which requires looping through the data twice, and several nested if/else statements. Indeed in this example, it gets up to five layers deep!

Which this example could be further refactored for [readability](https://github.com/wkorando/sip-of-java/blob/main/012-read-file-improvements/FileReaderIRefactored.md). As new requirements are added, imperative processes can become extremely difficult to follow, and subsequently modify and update.

```java
public class FileReaderI {
public static void main(String[] args) {
Expand Down Expand Up @@ -104,7 +110,9 @@ public class FileReaderI {
}
```

## Functional Porcessing with Streams
## Functional Processing with Streams

Accomplishing the same task functionally using Streams, looks like below. While the line count is similar to the imperative implementation above, streams does offer several distinct advantages, which will be covered below.

```java
public class FileReaderII {public class FileReaderII {
Expand Down Expand Up @@ -151,6 +159,13 @@ public class FileReaderII {public class FileReaderII {
}
```

### Skipping

### mapMulti

### Grouping and Ordering


## Other Streams Improvements

```java
Expand Down
24 changes: 16 additions & 8 deletions 012-read-file-improvements/script.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
Hey Java developers,

Getting lost in a maze of if statements and loops when processing large files?
Lost in a maze of if statements and loops when processing large files?

[Where am I?!]

been there, try using streams instead
been there,

try using streams instead

Streams, added in Java 8, improve the experience of processing large data sets

Transforming deeply nested if, else, and loop hierachies into a simple pipeline
Transforming deeply nested if, else, and loop hierarchies

Into a pipeline

With streams we can do a simple skip of the title line

Tokenize the values of a line and filter by date

Added in Java 16, mapMulti allow for 0 to n returns for an input
Added in Java 16, mapMulti allow for 0 to n returns

Being used here for handling when a mapping error occurs

Collectors, can be used for grouping and ordering items in a stream

Here being used for easy handling, when reading a row causes an error
Last we can handle the printing of the results with a forEach, instead needing a separate loop

Collectors, come with many pre-configured options for the grouping and ordering of items in a stream
Streams have seen a few other updates

Last we can handle the printing of the results, without a separate loop
With Java 16 returning a list can be done with .toList

If working with ordered data sets, consider takeWhile
When working with ordered data sets, consider takeWhile

Or dropWhile, both added in Java 9

Expand Down
7 changes: 4 additions & 3 deletions 012-read-file-improvements/src/main/java/FileReaderIII.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.BiConsumer;
Expand Down Expand Up @@ -44,12 +45,12 @@ public static void main(String[] args) {
.equals(currentMonth);

try (Stream<String> lines = Files.lines(Path.of(filename))) {
lines.skip(titleLine) //
.map(s -> s.split(",")).takeWhile(filterToCurrentMonth)//
List<ElectricProject> projects = lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
.values().stream().map(Optional::get).forEach(printResults);
.values().stream().map(Optional::get).toList();
} catch (IOException e) {
e.printStackTrace();
}
Expand Down
2 changes: 1 addition & 1 deletion 012-read-file-improvements/src/main/java/FileReaderIV.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static void main(String[] args) {

try (Stream<String> lines = Files.lines(Path.of(filename))) {
lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.map(s -> s.split(",")).takeWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
Expand Down
57 changes: 57 additions & 0 deletions 012-read-file-improvements/src/main/java/FileReaderV.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FileReaderV {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
Month currentMonth = Month.JUNE;
String filename = args[0];
long titleLine = 1L;

BiConsumer<String[], Consumer<ElectricProject>> mapElectricProject = (values, consumer) -> {
try {
consumer.accept(ElectricProject.map(values));
} catch (Exception e) {
// Do some cool stuff to handle errors
}
};

Consumer<ElectricProject> printResults = project -> {
System.out.println("""
City: %s
Project Number: %s
Expected Output: %s
""".formatted(project.city(), project.projectNumber(),
project.expectedKWhAnnualProduction().toString()));
};

Comparator<ElectricProject> compareExpectedKwhProduction = Comparator
.comparing(ElectricProject::expectedKWhAnnualProduction);

Predicate<String[]> filterToCurrentMonth = s -> LocalDate.parse(s[0], formatter).getMonth()
.equals(currentMonth);

try (Stream<String> lines = Files.lines(Path.of(filename))) {
lines.skip(titleLine) //
.map(s -> s.split(",")).dropWhile(filterToCurrentMonth)//
.mapMulti(mapElectricProject) //
.collect(Collectors.groupingBy(ElectricProject::city, TreeMap::new,
Collectors.maxBy(compareExpectedKwhProduction) )) //
.values().stream().map(Optional::get).forEach(printResults);
} catch (IOException e) {
e.printStackTrace();
}
}
}

0 comments on commit 34767c4

Please sign in to comment.