tansudasli / java-stream-sandbox

Java streams

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

java fundamentals - streams

This project is about

  • Collections API
  • Stream API
  • Collectors API
  • Functional API
  • parallelStreams

Stream concepts

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 get Stream<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 as collect(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))