Читаем Introducing Java 8 полностью

Here’s a step-by-step example so you can practice refactoring old-style Java code to use the Streams API. The following code filters invoices that are from a specific customer and related to training, sorts the resulting invoices by amount, and finally extracts the first five IDs: List oracleAndTrainingInvoices = new ArrayList<>(); List ids = new ArrayList<>(); List firstFiveIds = new ArrayList<>(); for(Invoice inv: invoices) { if(inv.getCustomer() == Customer.ORACLE) { if(inv.getTitle().contains("Training")) { oracleAndTrainingInvoices.add(inv); } } } Collections.sort(oracleAndTrainingInvoices, new Comparator() { @Override public int compare(Invoice inv1, Invoice inv2) { return Double.compare(inv1.getAmount(), inv2.getAmount()); } }); for(Invoice inv: oracleAndTrainingInvoices) { ids.add(inv.getId()); } for(int i = 0; i < 5; i++) { firstFiveIds.add(ids.get(i)); }

Now you’ll refactor this code step-by-step using the Streams API. First, you may notice that you are using an intermediate container to store invoices that have the customer Customer.ORACLE and "Training" in the title. This is the use case for using the filter operation: Stream oracleAndTrainingInvoices = invoices.stream() .filter(inv -> inv.getCustomer() == Customer.ORACLE) .filter(inv -> inv.getTitle().contains("Training"));

Next, you need to sort the invoices by their amount. You can use the new utility method Comparator.comparing together with the method sorted, as shown in the previous chapter: Stream sortedInvoices = oracleAndTrainingInvoices.sorted(comparingDouble(Invoice::getAmount));

Next, you need to extract the IDs. This is a pattern for the map operation: Stream ids = sortedInvoices.map(Invoice::getId);

Finally, you’re only interested in the first five invoices. You can use the operation limit to stop after those five. Once you tidy up the code and use the collect operation, the final code is as follows: List firstFiveIds = invoices.stream() .filter(inv -> inv.getCustomer() == Customer.ORACLE) .filter(inv -> inv.getTitle().contains("Training")) .sorted(comparingDouble(Invoice::getAmount)) .map(Invoice::getId) .limit(5) .collect(Collectors.toList());

You can observe that in the old-style Java code, each local variable was stored once and used once by the next stage. Using the Streams API, these throwaway local variables are eliminated.

Parallel Streams

The Streams API supports easy data parallelism. In other words, you can explicitly ask for a stream pipeline to be performed in parallel without thinking about low-level implementation details. Behind the scenes, the Streams API will use the Fork/Join framework, which will leverage the multiple cores of your machine.

All you need to do is exchange stream() with parallelStream(). For example, here’s how to filter expensive invoices in parallel: List expensiveInvoices = invoices.parallelStream() .filter(inv -> inv.getAmount() > 10_000) .collect(Collectors.toList());

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже