// MAX(*) is important here
SELECT id, MAX(value) from transactions
Reuse the same query for collections
No need to recreate MAX function with for loops
Leverage
// Filter by type
List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
if(t.getType() == Transaction.GROCERY){
groceryTransactions.add(t);
}
}
// Sort
Collections.sort(groceryTransactions, new Comparator(){
public int compare(Transaction t1, Transaction t2){
return t2.getValue().compareTo(t1.getValue());
}
});
// Select the ID only
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
transactionsIds.add(t.getId());
}
For loops
List<Integer> transactionsIds =
// Set of elements
transactions.stream()
// Intermediate operations
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
// Terminal operation, which executes the stream
.collect(toList());
Stream API
Stream Operations != Collection Operations
Library
list.stream() -> Stream.of(list)
.parallelStream()
List<Integer> transactionsIds =
// no more .stream()
transactions.parallelStream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> twoEvenSquares =
numbers.stream()
.filter(n -> {
System.out.println("filtering " + n);
return n % 2 == 0;
})
.map(n -> {
System.out.println("mapping " + n);
return n * n;
})
// Short-circuiting operation
.limit(2)
.collect(toList());
// Result
filtering 1
filtering 2
mapping 2
filtering 3
filtering 4
mapping 4
com.annimon.stream.Stream.java -> Ctrl + F -> "short-circuiting"
For Android
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> eventNumbers = Stream.of(numbers)
.filter(n -> {
System.out.println("filtering " + n);
return n % 2 == 0;
})
.limit(2)
.collect(Collectors.<Integer>toList());
Operators:
Classes:
List<String> words = new ArrayList() {{
add("Word");
add("Paper");
add("Word");
add("Android Rulez");
add("Device Information");
}};
Long distinctWords =
Stream.of(words)
.distinct()
.collect(Collectors.counting());
distinct
Long oneWordCount =
Stream.of(words)
.filter(p -> p.split(" ").length == 1)
.collect(Collectors.counting());
filter
String indexedSequence =
Stream.of(words)
.indexed()
.map(x -> String.format("%s %s ", x.getFirst(), x.getSecond()))
.collect(Collectors.counting());
// 0 Word 1 Paper 2 Word 3 Android Rulez 4 Device Information
indexed
Stream.of(words)
.sortBy(String::length)
.collect(Collectors.toList())
Sorting
Stream.of(words)
.sorted(Comparator)
.collect(Collectors.toList())
takeWhile / dropWhile / chunkBy
Stream.of("a", "b", "cd", "ef", "g")
.takeWhile(s -> s.length() == 1) // [a, b]
Stream.of("a", "b", "cd", "ef", "g")
.dropWhile(s -> s.length() == 1) // [cd, ef, g]
Stream.of("a", "b", "cd", "ef")
.chunkBy(String::length) // [[a, b], [cd, ef]]
filterNot / withoutNulls
map-filter-takeWhile-forEach*Indexed
Stream.of("a", "b", "c")
.mapIndexed((i, s) -> s + Integer.toString(i)) // [a0, b1, c2]
stream.filterNot(String::isEmpty)
Stream.of("a", null, "c", "d", null)
.withoutNulls() // [a, c, d]
average / sum
stream
.mapToDouble(w -> w.getTranslate().length())
.average() // only in mapToDouble
stream
.mapToInt(w -> w.getTranslate().length())
.sum()
.custom()
You can use Collectors to transform data into different types of structures like from List to Map etc.
TreeMap<String, List<PaymentResponse>> map =
Stream.of(sortedPayments)
.collect(
Collectors.groupingBy(PaymentResponse::getAccountId,
TreeMap::new,
Collectors.toList())
);
Custom Implementation
+
-