This project is about
- Collections API
- Stream API
- Collectors API
- Functional API
- parallelStreams
Collections API ::: General combinations
- not every combination makes sense
- some combinations are abstract, so you must implement
Concurrent | Linked | Array | List
Navigable | Hash | Map
Priority | Tree | Set
| Queue
| Table
Basicaly the meanings
- concurrent = thread-safe
- Array = index-based, better random access
- Linked = doubly-linked nodes, order preserved
- hash = hashed
LinkedHashMap = order-oreserved + hashed into buckets + k,v based store
Performances
insert delete get
- Array O(n) O(n) O(1)
- Linked O(1) O(1) O(n)
- Map O(1) O(1) O(1)
Collections API ::: Map
- Map means, one key = one value, But if you put a
List<V>
, you can hold many values for one key - default initial bucket = 16, load factor 0.75
- if (size = lf * initial) -> resize *= 2
- use .entrySet().stream() for streaming
- no duplicate key
- Map<k, v>, unsorted, no-null-key
- HashMap, unsorted, null-key,
- LinkedHashMap, insert-order, null-key
- ConcurrentHashMap, no-null-key, trade-safe
- TreeMap, sorted natural-order or Comparator-based
Get a stream from Regex
Stream<String> xx = Pattern.compile("\\w+).matcher("source").results()
Get a stream from File
- define
PATH = "..." as absolute path
Stream<String> xx = Files.lines(Paths.get(PATH))
Get a stream from SecureRandom
new SecureRandom()
.ints(10, 1, 7) //IntStream
.mapToObj(String::valueOf) //Stream<String>
.forEach(System.out::println)
Get a stream from int[] ::: primitives
IntStream<Integer> xx = Arrays.stream(int[])
- then
.boxed
to getStream<Integer>
, if you need!
Get a stream from Collections ::: wrappers
List<Integer> xx = new ArrayList<>(Arrays.asList(1, 3, 4))
Stream<Integer> yy = xx.stream()
Threading ::: in java-streams
-
if it is not parallel, same thread, sequential (beginning2end), gets a person then completes all-intermediate-steps. And, repeats the same as person and other tasks
1 thread 1 time (so no need for combiner) !! no need combiner (never enters addAll step) collect:::new N times sequentially map::: -> collect:::add N times, last step. terminal ops. sequential forEach:::
Threading ::: in java-parallelStreams
-
If it is parallel, leverages multi-threads, and all intermediate-steps can be happened in any order!. So, combiner is must!.
N thread N times collect::new (no optimization, which is interesting, that's why we need combiner!) -> collect::map -> collect::new -> collect::new -> collect::map -> collect::add ......... -> collect::addAll -> collect::new ...... N Thread -> colect returns ArrayList<>, so we need .parallelStream() again. Otherwise, it is not multi-threaded. @last step, foreach steps, (terminal operation)
Methods ::: Stream API vs Collectors API
some critical things changes the methods we may see!
- min vs Collectors.minBy
- Stream vs Stream (clipping to an integer type)
- IntStream vs Stream
- Transformation: IntStream -> boxed() -> Stream
stream().map()
is the same ascollect(Collectors.toMap()
- map (one by one mapping) vs Collectors.groupingBy (One by List mapping, so in downstream you may reduce it T also)
- (:Map<T extends Integer, List)
- if you have Map<k, v>, use
.entrySet().stream()
to do computing
.stream()
.map(::getIntegerTypeSomething) //Stream<Integer>
.min(Comparator.naturalOrder())
---
.stream()
.map(::getIntegerTypeSomething) //Stream<Integer>
.collect(Collectors.minBy(Comparator.naturalOrder()))
.stream()
.mapToInt(::getIntegerTypeSomething) //IntStream
.summaryStatistics()
---
.stream()
.collect(Collectors.summarizingInt(::getIntegerTypeSomething))