├── .gitignore ├── Cpp lvalue rvalue and between.md ├── Functional Programming In JS - Compositions And Transducers.md ├── Functional Programming in Java 8 - Basic Concepts and Lambdas.md ├── Git Cherry Picking.md ├── Introduction To Docker.md ├── Introduction To Git.md ├── Java Streams - Series ├── Java streams - Part 1 - What is a java stream.md ├── Java streams - Part 2 - Primitive steams.md ├── Java streams - Part 3 - Optional class.md ├── Java streams - Part 4 - Reduction.md ├── Java streams - Part 5 - Collectors.md ├── Java streams - Part 6 - Spliterator.md ├── Java streams - Part 7 - Parallel Streams.md ├── Java streams - Quiz.md ├── Java streams - Stream class methods.md └── README.md ├── README.md └── images ├── Git - cherry picking ├── 1.jpg ├── 1.psd ├── 2.jpg ├── 2.psd ├── 3.jpg └── 3.psd ├── Introduction To Docker ├── 1.jpg └── 1.psd └── Java streams in depth ├── 1.jpg ├── 1.psd ├── 2.jpg ├── 2.psd ├── 3.jpg ├── 3.psd ├── 4.jpg ├── 4.psd ├── 5.jpg ├── 5.psd ├── 6.jpg ├── 6.psd ├── 8.jpg └── 8.psd /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | *.class 5 | 6 | # Log file 7 | *.log 8 | 9 | # BlueJ files 10 | *.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | .mtj.tmp/ 14 | 15 | # Package Files # 16 | *.jar 17 | *.war 18 | *.ear 19 | *.zip 20 | *.tar.gz 21 | *.rar 22 | 23 | 24 | # LateX 25 | *.aux 26 | *.synctex.gz 27 | 28 | 29 | 30 | 31 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 32 | hs_err_pid* 33 | 34 | ~$*.pptx 35 | /gitgraph.js/ 36 | */*.arf 37 | /~$Introduction to Git by Stav Alfi.pptx 38 | /.idea/ 39 | /.DS_Store 40 | -------------------------------------------------------------------------------- /Cpp lvalue rvalue and between.md: -------------------------------------------------------------------------------- 1 | # C++ lvalue, rvalue and between By Stav Alfi 2 | 3 | ### Topics 4 | 5 | 1. [Introduction](#introduction) 6 | 2. [Object definitions](#object-definitions) 7 | 3. [Common misunderstanding](#common-misunderstanding) 8 | 4. [Expressions vs Types](#expressions-vs-types) 9 | 5. [Move consturctor and opertator](#move-constructor-and-operator) 10 | 6. [Source](#source) 11 | 7. [Complete terms table](#complete-terms-table) 12 | 8. [Legal](#legal) 13 | 14 | --- 15 | 16 | ### Introduction 17 | 18 | This tutorial attempts to clarify the common mistakes about the multiple invalid definitions for `lvalue` and `rvalue` expressions. 19 | 20 | ### Object definitions 21 | 22 | I will start by introducing the common, valid and different definitions for the term `object`. 23 | Throughout this tutorial, I will implicitly use the first definition. 24 | 25 | > **Definition 1.1.** An ___object in c programing language___ is an area in the memory which contain an address we can reach which _may_ contain data. 26 | 27 | For example, function or an instance of a struct. 28 | 29 | > **Definition 1.2.** An ___object in OPP___ is an instance of a class. 30 | 31 | Also I will define one more common term, I will use alot: 32 | 33 | > **Definition 1.3.** A ___temporary object___ is an object of class type. it does not have a _name_ (we can't reach this object after it's evaluation). It has an address on the stack and it will be destoryed __after__ evaluating the full expression which which has a "some link" to the expression who created that temporary object, unless we _named_ that temporary object. By naming I mean, creating a "way" to reach that temporary object which the compiler approve (This tutorial will teach you how to do it). 34 | 35 | ###### Examples: 36 | From definition 1.3: "it will be destoryed after evaluating the expression which created him...": 37 | ```java 38 | struct A { 39 | A(){ 40 | cout<<"A::A()"< Historically, lvalues and rvalues were so-called because they could appear on the left- and right-hand side of an assignment (although this is no longer generally true); ... Despite their names, these terms classify expressions, not values. 90 | 91 | ### Expressions vs Types 92 | 93 | ![](https://i.imgur.com/hMZPzj4.png) 94 | 95 | To better understand what are `lvalue` and `rvalue` expressions, lets define the following expressions: 96 | 97 | > **Definition 2.1.** A ___glvalue___ is an expression which it's evaluation is an _object, function or bitfield_ which we can choose _(we can also choose not)__ to refer later (_later_ is equal to - after the evaluation of the given expression). 98 | 99 | By definition, __any__ expressions which it's evaluation is a reference to object type, are also glvalue expression. 100 | 101 | ###### Examples: 102 | 103 | ```java 104 | int f(); // glvalue - this expression is a function. by defenition, this expression is a glvalue. 105 | &f; // glvalue - this expression evaluates a pointer which we can refer to later. 106 | // by defenition, this expression is a glvalue. 107 | f(); // not glvalue - this expression evaluates a call to function f which return a temporary value. 108 | // we can't refer to that specific temporary value because after the function will finish executiong, 109 | // the temporary object will be destoryed. 110 | ``` 111 | 112 | ```java 113 | class A{ 114 | int k; 115 | const A& f1() { return A();} // compiler warning: returning reference to temporary. 116 | const int& f2() { return k;} // note: k is glvalue. 117 | }; 118 | 119 | A a; 120 | a.f1(); // it doesn't matter if this expression is a glvalue or not. 121 | // it's undefined - can't use the returned object. it already destoryed. 122 | a.f2(); // glvalue - this expression return a const reference to k. k can be accessed (refer to) after evaluating this expression. 123 | ``` 124 | 125 | ```java 126 | const int x=4; 127 | x; // glvalue - x can be accessed after executing this expression. 128 | ``` 129 | 130 | ```java 131 | int i; 132 | int* p = &i; 133 | int& f(); 134 | int&& g(); // note: T&& is eventually a reference to object of type T. * We will talk about how is it different from T& soon. * 135 | 136 | int h(); 137 | 138 | h(); // not glvalue 139 | g(); // glvalue 140 | f(); // glvalue 141 | i; // glvalue 142 | *p; // glvalue 143 | ``` 144 | 145 | ###### end of examples 146 | 147 | We noticed that a `glvalue` expression evaluate object or reference which can __sometimes__ be assigned too and __always__ can be read from. 148 | 149 | `glvalue` expression is a `lvalue` or a `xvalue` expression only. 150 | 151 | To better understand what is a `xvalue` expression, first we need to understand what are `prvalue` expression and `rvalue reference` type. 152 | 153 | > __Definition 2.2.__ A ___prvalue___ (pure rvalue) is an expression which it's evaluation is a _temporary object_. 154 | 155 | ###### Examples: 156 | 157 | ```java 158 | int f1() { return 6 }; 159 | 160 | 6; // prvalue 161 | f1(); // prvalue 162 | ``` 163 | 164 | ###### end of examples 165 | 166 | > __Definition 2.3.__ A ___rvalue reference___ is a type (not an expression) of a special reference: `T&&` or `const T&&`. An _rvalue reference_ is a reference to temporary object. 167 | 168 | __Important note:__ As soon as there are no active references to that temporary object (it can happen after the end of scope of all `rvalue references` to this temporary object), this temporary object will be destoryed. We will use this note later on. 169 | 170 | ###### Examples: 171 | 172 | ```java 173 | const int&& f1() { return 6; } // f1 return type is rvalue reference. 174 | A&& f2() { return A(); } // f2 return a reference to prvalue. 175 | 176 | int&& x=f1(); // x is a reference. to be more precise - it is a rvalue reference 177 | // (soon we will be able to answer what excatly is the expression f() ). 178 | ``` 179 | 180 | ###### end of examples 181 | 182 | ###### Common mistake: 183 | 184 | __False claim:__ if expression `e` is a `rvalue reference` expression, 185 | then `e` is a `lvalue` expression. 186 |
187 | __Contradiction:__ `rvalue reference` is a type and not an expression. 188 | 189 | ###### End of common mistake 190 | 191 | There are 4 ways to create an `rvalue reference` type: 192 | 193 | 1. Return from a function a temporary object - `int&& f1() { return 6; }` 194 | 2. Assigning a temporary object directrly to `rvalue reference`varaible. 195 | 3. `static_cast(....)` - `int&& x = static_cast(6);` 196 | 4. `std::move(....)` - `int&& x = std::move(6);` 197 | 198 | `std::move` source code: 199 | 200 | ```java 201 | /** 202 | * @brief Convert a value to an rvalue. 203 | * @param __t A thing of arbitrary type. 204 | * @return The parameter cast to an rvalue-reference to allow moving it. 205 | */ 206 | template 207 | constexpr typename std::remove_reference<_Tp>::type&& 208 | move(_Tp&& __t) noexcept 209 | { return static_cast::type&&>(__t); } 210 | ``` 211 | 212 | > Definition 3.3. A _recursive_ definition to ___xvalue___ is a _glvalue_ expression which is one of the following forms: 213 | > 1. A call to a function which return a _rvalue reference_ to an object of type _T_ (not function). 214 | > 2. a convert _to_ type of _rvalue reference_. (for example, `static_cast(...)`). 215 | > 3. an access to _xvalue_ expression's class member `c`. The evaluation of a _xvalue_ expression must be an object of type _T_. 216 | 217 | 218 | ###### Examples: 219 | 220 | ```java 221 | struct A{ int data; }; 222 | 223 | int&& i; 224 | int& f(); 225 | int&& g(); 226 | A&& g1(); 227 | 228 | int h(); 229 | 230 | h(); // not glvalue - rvalue 231 | g(); // glvalue - xvalue 232 | g().data; // glvalue - xvalue 233 | f(); // glvalue - lvalue 234 | i; // glvalue - lvalue 235 | ``` 236 | 237 | ```java 238 | const int&& f1() { return 6; } // f1 return rvalue reference - a reference to rvalue expression. 239 | 240 | int&& x=f1(); 241 | x; // glvalue - lvalue 242 | f1(); // glvalue - xvalue 243 | ``` 244 | 245 | ###### end of examples 246 | 247 | > __Definition 4.1.__ A ___rvalue___ is an expression which is not a _lvalue_. 248 | 249 | Note: A _xvalue_ expression can be considered to be `glvlue` and `rvalue` expressions. 250 | 251 | There are 2 ways to create `rvalue` expression: expression which it's evaluation is `xvalue` or `prvalue`. We will see now that there is an implicit cast from `prvalue` expression's evaluation (which is an object) to oject of type `rvalue reference`. 252 | 253 | ### Move constructor and operator: 254 | 255 | ##### Move constructor 256 | 257 | As we saw earlier, we can't modify a temporary objects or even modify a non-static member of a class though `prvalue` expressions. Trying to do so, will lead to compilation error: `using temporary as lvalue`. 258 | 259 | ###### Examples: 260 | ```java 261 | struct A { 262 | int* bigArray; 263 | A():bigArray(new int[2^64]) { 264 | cout<<"A::A()"<bigArray; 273 | } 274 | }; 275 | 276 | A f1() { 277 | cout<<"f1()"<>here<<--)`. 332 | 333 | How do we accomplish it? By creating additional consturctor: _move consturctor_ in `A` class: 334 | 335 | ```java 336 | A(A&& a) { 337 | cout<<"A::A(A&& a)"<bigArray=a.bigArray; 339 | // when the destructor of the temporary object which `a` is 340 | // referencing to is called, our bigArray won't be deleted. 341 | a.bigArray=nullptr; 342 | } 343 | ``` 344 | 345 | Thats it! 346 | 347 | ```java 348 | f1() 349 | A::A() 350 | A::A(A&& a) 351 | A::~A() 352 | A::A(A&& a) 353 | f2(A a) 354 | A::~A() 355 | A::~A() 356 | end of f2(f1()); 357 | ``` 358 | Same as for operator move. 359 | 360 | ### Source: 361 | * [C++ standard](http://eel.is/c++draft/basic.lval) 362 | * [stackoverflow.com - user2079303's answer](https://stackoverflow.com/a/47956898/806963) 363 | * [stackoverflow.com](https://stackoverflow.com/questions/27364787/glvalue-real-examples-and-explanation/27364969#27364969) 364 | * [thbecker.net](http://thbecker.net/articles/rvalue_references/section_03.html) 365 | 366 | ### Complete terms table 367 | 368 | > **Definition 1.1.** An ___object in c programing language___ 369 | is an area in the memory which contain an address we can reach which _may_ contain data. 370 | 371 | > **Definition 1.2.** An ___object in OPP___ is an instance of a class. 372 | 373 | > **Definition 1.3.** An ___temporary object___ is an object of class type. it does not have a _name_ (we can't reach this object after it's evaluation). It has an address on the stack and it will be destoryed __after__ evaluating the full expression which which has a "some link" to the expression who created that temporary object, unless we _named_ that temporary object. By naming I mean, creating a "way" to reach that temporary object which the compiler approve (This tutorial will teach you how to do it). 374 | 375 | > **Definition 2.1.** A ___glvalue___ is an expression which it's evaluation __(not the actual value it evaluates)__ 376 | is an _object, function or bitfield_ which we can choose __(we can also choose not)__ to refer later 377 | (_later_ is equal to - after the evaluation of the given expression). 378 | 379 | > __Definition 2.2.__ A ___prvalue___ (pure rvalue) is an expression which it's evaluation is a temporary object. 380 | A temporary object can't be refer to after we evaluate it. 381 | 382 | > __Definition 2.3.__ A ___rvalue reference___ is a type (not an expression) of a special reference: `T&&` or `const T&&`. An _rvalue reference_ is a reference to temporary object. 383 | 384 | > __Definition 2.4.__ A ___rvalue___ is an expression which is not a _lvalue_. 385 | 386 | ### Legal 387 | 388 | © Stav Alfi, 2017. Unauthorized use and/or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear 389 | credit is given to Stav Alfi with appropriate and specific direction to the original content. 390 | 391 | Creative Commons License "C++ lvalue, rvalue and between By Stav Alfi" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 392 | Based on a work at https://gist.github.com/stavalfi/52560f2b0d57d97b34ecae21f0bc9fa9. 393 | -------------------------------------------------------------------------------- /Functional Programming in Java 8 - Basic Concepts and Lambdas.md: -------------------------------------------------------------------------------- 1 | # Functional Programming in Java 8 - Basic Concepts and Lambdas By Stav Alfi 2 | 3 | ### Topics 4 | 5 | 1. [Introduction](#introduction) 6 | 2. [Functional Interface](#functional-interface) 7 | 3. [java.util.function package](#javautilfunction-package) 8 | 4. [Lambda Expression](#lambda-expression) 9 | 5. [Variable scope](#variable-scope) 10 | 6. [Anonymous class](#anonymous-class) 11 | 7. [Method reference types](#method-reference-types) 12 | 8. [Quiz](#quiz) 13 | 9. [Conclusion](#conclusion) 14 | 15 | ### Additional 16 | 17 | 1. [Complete terms table](#complete-terms-table) 18 | 2. [Variable scope table](#variable-scope-table) 19 | ------ 20 | 21 | ### Introduction 22 | This article is meant to build a common language with the reader which will be used to answer the following questions: What are _free variables_? Are we allowed to change them inside the lambda expression? Is it considered dangerous to mutate them? 23 | 24 | __Prerequirements__ 25 | 26 | It is highly recommended that you will control Java Generics. 27 | 28 | __Acknowledgements__ 29 | 30 | The people listed below have provided feedback and edit which has helped improve the quality of this article. 31 | 32 | @damirbar - Special thanks to Damir Bar for acting as the provisional grammar consultant. 33 | 34 | --- 35 | 36 | ### Functional Interface 37 | 38 | > **Definition 1.1.** ___Functional Interfaces___ are interfaces containing single abstract method and any number of default/static methods. 39 | 40 | The compiler will define those interfaces as _functional Interfaces_. Also, we can add particular annotation above the interface, so the compiler will warn us if we declare more then one abstract function inside the interface. 41 | 42 | Also, the Javadoc will explicitly mention that this interface is a _Functional interface_. 43 | 44 | The compiler permits us to not explicitly add the `@FunctionalInterface` annotation to an interface with one abstract method so the interface will be _functional Interfaces_, it is optional and recommended. 45 | 46 | ```java 47 | @FunctionalInterface 48 | interface MyInterface 49 | { 50 | void f1(); 51 | } 52 | ``` 53 | 54 | **An important note about exceptions** - In a case that the method which overrides `f1` can throw exceptions, the declaration of `f1` inside the _functional Interface_ must consist of the possible exceptions which `f1` may throw: 55 | ```java 56 | @FunctionalInterface 57 | interface MyInterface 58 | { 59 | void f1() throws Exception, DataFormatException, IOException; 60 | } 61 | ``` 62 | The following section contains common _functional interfaces_. 63 | 64 | ### java.util.function package 65 | 66 | The most common _functional interfaces_ defined in `java.util.function` package. More specific _functional interfaces_ defined in other packages. 67 | 68 | |Interface::Method | Parameters Type| Return Type| More Info 69 | |:----| :----:| :----:|:----| 70 | |`Function::apply` | `T` | `R` | | 71 | |`Consumer::accept` | `T` | `void` | Expected to operate via side-effects | 72 | |`Predicate::test` | `T` | `boolean` | | 73 | |`Supplier::get` | None | `T` | | 74 | |`BiFunction::apply` | `T`,`U` | `R` | | 75 | |`UnaryOperator implements Function` | `T` | `T` | | 76 | |`BinaryOperator implements BiFunction`| `T`,`T` | `T` | | 77 | |`ToIntFunction::applyAsInt` | `T` | `int` | | 78 | |`DoubleConsumer::accept` | `double` | `void` | Expected to operate via side-effects | 79 | |`ObjIntConsumer::apply` | `Object`,`int` | `void` | Expected to operate via side-effects | 80 | 81 | Note: Do not create your own _functional interfaces_., instead use what Java provides in `java.util.function` package or any other packages. You should also read and memorize the use case of each _functional interface_. For example, by using `Predicate` interface, you should only check if an input parameter is fulfilled in some conditions. You should not do any side effects in the process because the caller will assume you are using this interface as java recommended you to use it. 82 | 83 | Understanding `side-effects` is not mandatory to get the idea and use lambdas. 84 | 85 | > **Definition 1.2.** A function or expression is said to have a ___side effect___ if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value. 86 | 87 | An essential concept in _functional programming_ is also _pure functions_. 88 | 89 | > **Definition 1.3.** A function may be considered a ___pure function___ if both of the following statements about the function hold: 90 | > 1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while a program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. 91 | > 92 | >2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices. 93 | 94 | ### Lambda Expression 95 | 96 | Java 8 introduced a new feature which takes us one step toward functional programming. It is the ability to create functions at runtime with lambda expressions. 97 | 98 | > **Definition 2.1.** A variable which wasn't defined as final, but never changed is also ___effectively final___. 99 | 100 | > **Definition 2.2.** By referring ___free variables___ of a function, we refer to all the variables that weren't define inside the function nor parameters of that function. 101 | 102 | > **Definition 2.3.** ___Lambda Expression___ is the method implementation of a _functional interface_. It has zero or more parameters and a body that will (or not) execute at a later stage. Inside the body, we have access to its _free variables_. 103 | 104 | ```java 105 | Function lambda1=(Integer a) -> a+1 ; 106 | ``` 107 | 108 | Let's break it down: 109 | 110 | 1. `Function` is the _Functional Interface_ that the lambda is implementing. 111 | 2. The `Function` interface contains, as expected, a single method which accepts an Integer as a parameter and returns Integer. 112 | 3. `lambda1` is the name of the object from a class implementing `Function` interface. 113 | 4. `(.....)` contains all the parameters of the lambda. The number of parameters and their types must correspond to the declaration of the instance method inside `Function`. 114 | 5. `->` separates the parameters and the body of the lambda. 115 | 6. `a+1` is the body of the lambda. It returns the value of `a+1`. In case the body has more than one line, use `{`, `}` : 116 | ```java 117 | int x=10; 118 | Function lambda2=(Integer a) -> { 119 | a++; 120 | return a+x; 121 | } 122 | ``` 123 | To invoke the lambda: 124 | ```java 125 | int y=lambda2.applay(10); 126 | ``` 127 | `y` will be initilize with the value `21`. 128 | 129 | ### Variable scope 130 | 131 | | Variable scope | Read | Write | More Info | 132 | | :-----------------| :-----: | :--------: | :--------------------------------------: | 133 | | Lambda expression | `T` | `T` | | 134 | | Enclosing method | `T` | `F` | Must be _final_ or _effectivly final_ | 135 | | Enclosing class | `T` | `T` | | 136 | 137 | __Why can't we write to a variable created at the enclosing method?__ 138 | 139 | 1. To avoid additional synchronizations while running the enclosing method and the lambda body in parallel. 140 | 141 | 2. The lifetime of a variable created at the enclosing method may have a shorter life than the lambda itself. In other words, the lambda may be invoked after the enclosing method returned. It means we will write to a variable that may not exist. 142 | 143 | We conclude that the lambda must keep somehow a copy of all the variables it uses in the enclosing method. The current implementation of Java **may** add all the variables (in the enclosing method or class) the lambda read or write to the list of parameters the lambda get. It **may** also add only the variables from the enclosing method to the list of parameters because the rest can be reached in other ways. The lambda it private static method or private instance method inside the enclosing class. The decision of making it static method or instance method is decided by (can be changed in the future): If the lambda does not use any variable of the enclosing class, it **may** become a static method. Else it **may** become an instance method. 144 | 145 | For example: 146 | 147 | ```java 148 | public class A { 149 | 150 | public static void main(String[] args) { 151 | Consumer f2 = (Integer x) -> System.out.print(x); 152 | } 153 | } 154 | ``` 155 | After complining: 156 | ```java 157 | javac A.java 158 | javap -p A 159 | ``` 160 | Output: 161 | ```java 162 | Compiled from "A.java" 163 | public class A { 164 | public A(); 165 | public static void main(java.lang.String[]); 166 | private static void lambda$main$0(java.lang.Integer); 167 | } 168 | ``` 169 | 170 | Another example: 171 | 172 | ```java 173 | public class A { 174 | 175 | int y=9; 176 | public void f1() { 177 | Consumer f2 = (Integer x) -> System.out.print(y); 178 | } 179 | } 180 | ``` 181 | After complining: 182 | ```java 183 | javac A.java 184 | javap -p A 185 | ``` 186 | Output: 187 | ```java 188 | Compiled from "A.java" 189 | public class A { 190 | int y; 191 | public A(); 192 | public void f1(); 193 | private void lambda$f1$0(java.lang.Integer); 194 | } 195 | ``` 196 | 197 | ### Anonymous class 198 | 199 | It is a common mistake that lambdas translated to objects of anonymous classes that implement the functional interface. When creating an object of an anonymous class, first a class file is generated and then a new object is initialized. Creation of a file for each object of an anonymous class is a huge overhead to the VM in runtime when lambdas are widely used in every application. 200 | 201 | ### Method reference types 202 | 203 | When your lambda has one line, calls a method with all the parameters of the lambda and return what that function returns then you better use method reference. 204 | 205 | 206 | The following line 207 | ```java 208 | Consumer lambda1 = (Integer a) -> System.Out.println(a); 209 | ``` 210 | is recoomended to be written as: 211 | ```java 212 | Consumer lambda1 = System.Out::println; 213 | ``` 214 | The parameter of the lambda is used for calling to the method `println` without us needing to write them explicitly. 215 | 216 | There are 4 types of Method references: Object::instanceMethod, Class::staticMethod, class::InstanceMethod and class::contructor. 217 | 218 | __Object::instanceMethod__ 219 | 220 | as the name implies, the lambda calls a method of an object. The first example applies here too: 221 | ```java 222 | Consumer lambda1 = System.Out::println; 223 | lambda1.accept("hi!!"); // will print: hi!! 224 | ``` 225 | 226 | __Class::staticMethod__ 227 | 228 | ```java 229 | public class App { 230 | 231 | private static int f1() { 232 | return 10; 233 | } 234 | 235 | public static void main( String[] args ) 236 | { 237 | Supplier lambda1=App::f1; // () -> App.f1(); 238 | int x=lambda1.get(); // x = 10 239 | } 240 | } 241 | ``` 242 | 243 | __class::InstanceMethod__ 244 | 245 | The first parameter will invoke one of his methods and use the second parameter as an argument: 246 | 247 | ```java 248 | public class App { 249 | 250 | public int f1() { 251 | return 8; 252 | } 253 | 254 | public static void main( String[] args ) throws IOException 255 | { 256 | Function lambda1 = App::f1; // (App a)-> a.f1(); 257 | int x = lambda1.applay(new App()); // x = 8 258 | } 259 | } 260 | ``` 261 | ```java 262 | public class App { 263 | 264 | public int f2(App a) { 265 | return 16; 266 | } 267 | 268 | public static void main( String[] args ) throws IOException { 269 | BiFunction lambda1 = App::f2; // (App a,App b) -> a.f2(b); 270 | int y = lambda1.applay(new App()); // y = 16 271 | } 272 | } 273 | ``` 274 | __class::contructor__ 275 | 276 | ```java 277 | Function lambda1 = int[]::new; // (int x)-> new int[x]; 278 | int[] array = lambda1.apply(10); 279 | ``` 280 | 281 | ```java 282 | class A 283 | { 284 | public static void main(String[] args) 285 | { 286 | Supplier lambda1 = A::new; // (int x)-> new A(); 287 | A a1 = lambda1.get(); 288 | } 289 | } 290 | ``` 291 | 292 | __Note:__ It is possible to use `super`/ `this` as an object inside methods: 293 | ```java 294 | class A 295 | { 296 | void f1(int x) 297 | { 298 | System.out.println("father is printing!"); 299 | } 300 | } 301 | ``` 302 | ```java 303 | class B extends A 304 | { 305 | B() 306 | { 307 | Consumer lambda1 = super::f1; // (int x) -> super.f1(x); 308 | lambda1.accept(10); // print: father is printing! 309 | } 310 | void f1(int x) 311 | { 312 | System.out.println("son is printing!"); 313 | } 314 | } 315 | ``` 316 | ### Quiz 317 | The Answers are at the end of the quiz. 318 | 319 | ###### Question 1 320 | 321 | Search for `Runnable` funcation interface's method signature. Could we write inside the following code: `Runnable runnable1 = this::f1;`? Name a _readability_ disadvantage while sending `this::f1` as a parameter to a method. 322 | ```java 323 | // Class MyClass1 324 | public void f2() { 325 | Runnable runnable1 = () -> { 326 | System.out.println("hi"); 327 | }; 328 | } 329 | 330 | public void f1() { 331 | System.out.println("hi"); 332 | } 333 | ``` 334 | [Answer 1](#1-question-with-answer) 335 | 336 | ###### Question 2 337 | 338 | What are the differences between the following _functional interfaces_: `Runnable`, `Callable` and `Comparable`? Write lambdas using those _functional interfaces_ and test them out. 339 | 340 | [Answer 2](#2-question-with-answer) 341 | 342 | ###### Question 3 343 | 344 | What are the differences between _side effects_ and _pure function_? 345 | 346 | [Answer 3](#3-question-with-answer) 347 | 348 | ###### Question 4 349 | 350 | What are the four main new _funcational interfaces_ in `Java 8`? Which of them can be implemented with _side effects_ or _pure function_? 351 | 352 | [Answer 4](#4-question-with-answer) 353 | 354 | ###### Question 5 355 | 356 | What does the following code prints? 357 | ```java 358 | Predicate p1 = (Integer x) -> x % 2 == 0; 359 | Predicate p2 = (Integer x) -> x % 3 == 0; 360 | 361 | System.out.println(p1.or(p2).test(1)); 362 | System.out.println(p1.and(p2).test(2)); 363 | System.out.println(p1.and(p2).and(p1).test(3)); 364 | System.out.println(p1.negate().test(4)); 365 | ``` 366 | 367 | [Answer 5](#5-question-with-answer) 368 | 369 | ###### Question 6 370 | 371 | Fill the types which are missing (`Type1`,`Type2`,`Type3`): 372 | ```java 373 | Function f1=(Integer x)->"hi"+x; 374 | f1.andThen((Type3 something)->something.length()); 375 | ``` 376 | What does this code prints? 377 | 378 | [Answer 6](#6-question-with-answer) 379 | 380 | ###### Question 7 381 | 382 | What does this code prints? 383 | ```java 384 | Function f1 = (String x) -> x.length(); 385 | Integer[] x = f1.andThen((Integer number) -> new Integer[number]) 386 | .apply("123"); 387 | ``` 388 | 389 | [Answer 7](#7-question-with-answer) 390 | 391 |

392 | In the following questions, you need to determine if there is any compilation error, undefined behavior or there is nothing wrong. They are confusing and tricky. Take your time and explain your answer with as many details as possible. 393 | 394 | ###### Question 8 395 | 396 | Assume all the threads don't fail to run. 397 | 398 | ```java 399 | static int count=1; 400 | public static void f1() { 401 | 402 | for(int i=1;i<=10;i++) 403 | new Thread(()->count++).start(); 404 | } 405 | ``` 406 | 407 | [Answer 8](#8-question-with-answer) 408 | 409 | ###### Question 9 410 | 411 | Assume all the threads don't fail to run. 412 | 413 | ```java 414 | public static void f2() { 415 | 416 | for(int i=1;i<=10;i++) 417 | new Thread(()->System.out.println(i)).start(); 418 | } 419 | ``` 420 | 421 | [Answer 9](#9-question-with-answer) 422 | 423 | #### Answers: (With the questions) 424 | 425 | ###### 1. Question with Answer 426 | 427 | ###### Question 428 | 429 | Search for `Runnable` funcation interface's method signature. Could we write inside the following code: `Runnable runnable1 = this::f1;`? Name a _readability_ disadvantage while sending `this::f1` as a parameter to a method. 430 | ```java 431 | // Class MyClass1 432 | public void f2() { 433 | Runnable runnable1 = () -> { 434 | System.out.println("hi"); 435 | }; 436 | } 437 | 438 | public void f1() { 439 | System.out.println("hi"); 440 | } 441 | ``` 442 | ###### Answer 443 | 444 | Yes, we could. The implementation of `Runnable` function interface is: 445 | ```java 446 | @FunctionalInterface 447 | public interface Runnable { 448 | public abstract void run(); 449 | } 450 | ``` 451 | 452 | To understand the disadvantage, let us examine the following code: 453 | 454 | ```java 455 | class Application{ 456 | static void doSomeWork() {} 457 | 458 | static void f2(Runnable r1) { 459 | r1.run(); 460 | } 461 | 462 | static void doSomeWork(String str) {} 463 | 464 | static void f3(Consumer r1) { 465 | r1.accept("333333"); 466 | } 467 | 468 | public static void main(String[] args) { 469 | // part A 470 | f2(() -> doSomeWork()); // line 1 471 | f2(Application::doSomeWork); // line 2 472 | // Part B 473 | f3((String str) -> doSomeWork(str)); // line 3 474 | f3(Application::doSomeWork); // line 4 475 | } 476 | } 477 | ``` 478 | In line `1` we are sending to `f2` a lambda which calls `doSomeWork` with no params. We __explicitly see__ that we dont send any params and `doSomeWork` does not get any params. in line `2` we can't __explicitly see__ it; in line `2` we must go to the signature of `doSomeWork` (which we will find 2 of them) and understand if `doSomeWork` get params or not. The only way to understand which overload of `doSomeWork` we need to look into is by looking at the signature of `f2` and see that it gets `Runnable` which means that the overload of `doSomeWork` we are searching for, doesn't get any params. 479 | 480 | We have the same problem of readability in line `4`. It means that by the only __looking with our eyes__ at lines `2` and `4`, we can't understand what the signature of `doSomeWork` is and we can't understand that there are two overloads to `doSomeWork` method. But by looking at lines `1` and `3`, we can easily see that there are two overloads to the method `doSomeWork`. 481 | 482 | [Question 2](#question-2) 483 | 484 | ###### 2. Question with Answer 485 | 486 | ###### Question 487 | 488 | What are the differences between the following _functional interfaces_: `Runnable`, `Callable` and `Comparable`? Write lambdas using those _functional interfaces_ and test them out. 489 | 490 | ###### Answer 491 | 492 | The functional interfaces' method signatures: 493 | 494 | ```java 495 | @FunctionalInterface 496 | public interface Runnable { 497 | public abstract void run(); 498 | } 499 | 500 | @FunctionalInterface 501 | public interface Callable { 502 | V call() throws Exception; 503 | } 504 | 505 | // it is optional to specify @FunctionalInterface here. 506 | public interface Comparable { 507 | public int compareTo(T o); 508 | } 509 | ``` 510 | 511 | They all have a different signature, so they not the same. Also, by the implementation details(java docs) we can see that they are intended for different use cases. The only way to know them is to read them. Misusing them will lead to bugs between different developers. 512 | 513 | [Question 3](#question-3) 514 | 515 | ###### 3. Question with Answer 516 | 517 | ###### Question 518 | 519 | What are the differences between _side effects_ and _pure function_? 520 | 521 | ###### Answer 522 | 523 | The definitions from Wikipedia are: 524 | 525 | > **Definition 1.2.** A function or expression is said to have a ___side effect___ if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value. 526 | 527 | > **Definition 1.3.** A function may be considered a ___pure function___ if both of the following statements about the function hold: 528 | > 1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while the execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. 529 | > 530 | >2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices. 531 | 532 | [Question 4](#question-4) 533 | 534 | ###### 4. Question with Answer 535 | 536 | ###### Question 537 | 538 | What are the four main new _funcational interfaces_ in `Java 8`? Which of them can be implemented with _side effects_ or _pure function_? 539 | 540 | ###### Answer 541 | 542 | The four main new _functional interfaces_ in `Java 8` are: `Consumer`, `Supplier`, `Function` and `Predicate`. 543 | 544 | 1. `Consumer` - Get an object and do something with it. We are allowed to use _side effects here_. 545 | 2. `Supplier` - (from the java docs) Represents a supplier of results. 546 | There is no requirement that a new or distinct result be returned each time the supplier is invoked. 547 | 548 | It means we implement a `Supplier` not as a _pure function_. 549 | 550 | 1. `Function` - Get an object from type `A` and return object from type `B` (Type `A` can be equal to type `B`). No _side effects_ are allowed here. But sometimes we will implement it as a transformer from _id_ to an object we retrieved from a server. A server call has _side effects_. 551 | 552 | 2. `Predicate` - Get an Object a determine if it satisfies a condition. No _side effects_ are allowed here. No _side effects_ are permitted here. 553 | 554 | [Question 5](#question-5) 555 | 556 | ###### 5. Question with Answer 557 | 558 | ###### Question 559 | 560 | What does the following code prints? 561 | ```java 562 | Predicate p1 = (Integer x) -> x % 2 == 0; 563 | Predicate p2 = (Integer x) -> x % 3 == 0; 564 | 565 | System.out.println(p1.or(p2).test(1)); 566 | System.out.println(p1.and(p2).test(2)); 567 | System.out.println(p1.and(p2).and(p1).test(3)); 568 | System.out.println(p1.negate().test(4)); 569 | ``` 570 | 571 | ###### Answer 572 | 573 | It will print: 574 | ```java 575 | false 576 | false 577 | false // In this case, there is no effect to the extra `and(p1)`. 578 | false 579 | ``` 580 | 581 | [Question 6](#question-6) 582 | 583 | ###### 6. Question with Answer 584 | 585 | ###### Question 586 | 587 | Fill the types which are missing (`Type1`,`Type2`,`Type3`): 588 | ```java 589 | Function f1=(Integer x)->"hi"+x; 590 | f1.andThen((Type3 something)->something.length()); 591 | ``` 592 | What does this code prints? 593 | 594 | ###### Answer 595 | 596 | Solution: 597 | ```java 598 | Function f1=(Integer x)->"hi"+x; 599 | f1.andThen((String something)->something.length()); 600 | ``` 601 | The code doesn't print anything. We use `f1` as it was a normal object, which means we need to call one of it's methods to invoke something. In this case, we need to write `f1.apply(some value)`. 602 | 603 | [Question 7](#question-7) 604 | 605 | ###### 7. Question with Answer 606 | 607 | ###### Question 608 | 609 | What does this code prints? 610 | ```java 611 | Function f1 = (String x) -> x.length(); 612 | Integer[] x = f1.andThen((Integer number) -> new Integer[number]) 613 | .apply("123"); 614 | ``` 615 | 616 | ###### Answer 617 | 618 | This code prints nothing because we didn't send anything to the screen. But the call to `apply("123")` will return `integer[]{0,0,0}`. 619 | 620 | [Question 8](#question-8) 621 | 622 | ###### 8. Question with Answer 623 | 624 | ###### Question 625 | 626 | Assume all the threads don't fail to run. 627 | 628 | ```java 629 | static int count=1; 630 | public static void f1() { 631 | 632 | for(int i=1;i<=10;i++) 633 | new Thread(()->count++).start(); 634 | } 635 | ``` 636 | 637 | ###### Answer 638 | 639 | Answer: undefined.\ 640 | `count` is a static property so as a result, he will never be _effectivly final_. Also, we can read and write to a static variable from the lambda's body. Due to the absence of synchronization on `count`, we conclude that the result is undefined. 641 | 642 | [Question 9](#question-9) 643 | 644 | ###### 9. Question with Answer 645 | 646 | ###### Question 647 | 648 | Assume all the threads don't fail to run. 649 | 650 | ```java 651 | public static void f2() { 652 | 653 | for(int i=1;i<=10;i++) 654 | new Thread(()->System.out.println(i)).start(); 655 | } 656 | ``` 657 | 658 | ###### Answer 659 | 660 | Answer: Compilation error.\ 661 | `i` is a _free variable_ and also is a local variable of the enclosing function. `i` will be mutated after its initialization so it can't be used inside the lambda. It must be defined as defined as _final_ or _effectively final_. So the lambda can read it's value. 662 | 663 | ### Conclusion 664 | 665 | The big difference between method reference and lambda expression is method reference references to the method directly it should invoke. The lambda is responsible for invoking a method (in case there is a call to a method inside the lambda body). It means we called two methods instead of one. 666 | 667 | ------------------ 668 | 669 | ### Legal 670 | 671 | © Stav Alfi, 2017. Unauthorized use or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear 672 | credit is given to Stav Alfi with appropriate and specific direction to the original content. 673 | 674 | Creative Commons License "Lambda Expressions In Depth By Stav Alfi" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 675 | Based on a work at https://gist.github.com/stavalfi/e24178288973d104042d4162a02fd135. 676 | 677 | 678 | --- 679 | 680 | ### Complete terms table 681 | 682 | > **Definition 1.1.** ___Functional Interfaces___ are interfaces containing single abstract method and any number of default/static methods. 683 | 684 | > **Definition 1.2.** A function or expression is said to have a ___side effect___ if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value. 685 | 686 | > **Definition 1.3.** A function may be considered a ___pure function___ if both of the following statements about the function hold: 687 | > 1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while the execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. 688 | > 689 | >2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices. 690 | 691 | > **Definition 2.1.** A variable which wasn't defined as final, but never changed is also ___effectively final___. 692 | 693 | > **Definition 2.2.** By referring ___free variables___ of a function is all the variables didn't define inside the function nor parameters of that function. 694 | 695 | > **Definition 2.3.** ___Lambda Expression___ is the method implementation of a _functional interface_. It has zero or more parameters and a body that will (or not) execute at a later stage. Inside the body, we have access to its _free variables_. 696 | 697 | ### Variable scope table 698 | 699 | | Variable scope | Read | Write | More Info | 700 | | :-----------------| :-----: | :--------: | :--------------------------------------: | 701 | | Lambda expression | `T` | `T` | | 702 | | Enclosing method | `T` | `F` | Must be _final_ or _effectivly final_ | 703 | | Enclosing class | `T` | `T` | | 704 | -------------------------------------------------------------------------------- /Git Cherry Picking.md: -------------------------------------------------------------------------------- 1 | ### Git Cherry Picking by Stav Alfi 2 | 3 | 4 | 5 | ### Topics 6 | 7 | 1. [Introduction](#introduction) 8 | 2. [What is a cherry-pick](#what-is-a-cherry-pick) 9 | 3. [How does it work](#how-does-it-work) 10 | 4. [Multiple commits at once](#multiple-commits-at-once) 11 | 5. [Quiz](#quiz) 12 | 6. [Legal](#legal) 13 | 14 | --- 15 | 16 | ### Introduction 17 | 18 | The goal of this tutorial is for explaining what cherry-pick command is, how does it work and how to handle errors (conflicts). 19 | 20 | This tutorial does not focus on real-life examples which involve cherry-picking because those examples may be objective. However, I do say that `git cherry-pick` is a __prerequirement__ to understand `git rebase` which will be covered in the future tutorial. 21 | 22 | In this toturial I will explain the following cammands and files: 23 | 1. `git cherry-pick` 24 | 2. `cherry-pick --continue` 25 | 3. `cherry-pick --abort` 26 | 4. `git cherry-pick and so on` 27 | 5. `git cherry-pick ..` 28 | 6. `CHERRY_PICK_HEAD` file 29 | 30 | ###### Prerequirements 31 | 32 | I assume you fully understand the following git commands concepts: 33 | 1. `git am`. 34 | 2. `git diff` (especially _chunk_ and _chunk context_). 35 | 3. `git apply`. 36 | 4. `git merge-file`. 37 | 5. `git format-patch`. 38 | 6. _2 way merge_. 39 | 7. _3 way merge_. 40 | 8. _blob_. 41 | 42 | Also if you are not familiar with Git source control, basic git commands can be found here: [Introduction to Git by Stav Alfi](https://gist.github.com/stavalfi/1020abe20960c2daf215410da56250eb) 43 | 44 | --- 45 | 46 | ### What is a cherry-pick 47 | 48 | The [formal definition](https://git-scm.com/docs/git-cherry-pick) is: 49 | 50 | > ___git-cherry-pick___ - Apply the changes introduced by some existing commits. 51 | 52 | A quick definition to their definition can be: _cherry-pick_ means to copy a commit from somewhere and _git am_ it where the active branch is on. 53 | 54 | For example, in the following graph where`HEAD` is looking at the blue (top) branch, we want to copy commit 4 to the blue branch: 55 | 56 | ![](https://i.imgur.com/FGyDQKO.jpg) 57 | 58 | ```git 59 | git checkout blue-branch 60 | git cherry-pick commit-4 61 | ``` 62 | ![](https://i.imgur.com/uthHw1m.jpg) 63 | 64 | Theoretically, we could copy `commit-2` instead (technically, this will probably won't work; We will talk about it later): 65 | 66 | ![](https://i.imgur.com/p1ZPzNK.jpg) 67 | 68 | ### How does it work 69 | 70 | When we are cherry-picking, Git does not copy a commit but check what has changed between the commit we want to copy, and it's parent. Then Git _try_ to create a new commit from that _patch_ on where the active branch is. 71 | 72 | I will describe the algorithm `git cherry-pick` use as pseudocode: 73 | 74 | ![](https://i.imgur.com/FGyDQKO.jpg) 75 | 76 | ```git 77 | git checkout blue-branch 78 | git cherry-pick commit-4 79 | ``` 80 | 81 | _Start of pseudo code_ 82 | 83 | 1. Git uses `diff` between `commit-3` and `commit-4` and saves it as a `patch`: 84 | `git format-patch -1 commit-4` - this means, create a patch from the diff between `commit-4` and `1` commit back which is `commit-3`. 85 | 2. Git tries to `apply` the patch we created on where the active branch is: 86 | `git apply --index the-patch-git-created-in-step-1`. `--index` will apply the patch to the index also. 87 | 3. Success. Git commits all the changes in the index file to create a new commit. The active branch will point to the new commit. __Finish__. 88 | 4. Fail. Git fails to apply some of the chunks in the patch. There can be 2 reasons for the failure: 89 | * if the _chunk_ is, for example, about a change occurred in file `A.txt`, Git didn't find file `A.txt` inside `commit-6`. 90 | * Inside the file which the chunk needs to be applied, Git didn't find the _chunk contex_ or Git found the context but the line it should change is missing or changed already. In other words, if the _chunk_ is, for example, about a change occurred in file `A.txt`, Git search inside file `A.txt` inside `commit-6` the _chunk context_ (3 lines before the lines which should be changed` or 3 lines after them), but it failed to find them or the lines which should be changed because those lines are missing or changes already. 91 | 5. The chunks which successfully applied will stay inside the working directory, and the index but the Git will try to do one last and single.. rescue for you with _3 way merge_ to the specific chunks which failed to apply. Let us look inside a patch and analyze it: 92 | 93 | ```java 94 | From 3282a02b0f3f1c49bcd3869a31c3842eaa76f7c6 Mon Sep 17 00:00:00 2001 95 | From: stav alfi 96 | Date: Wed, 8 Nov 2017 22:11:40 +0200 97 | Subject: [PATCH] 2 98 | 99 | --- 100 | 1.txt | 2 +- 101 | 1 file changed, 1 insertion(+), 1 deletion(-) 102 | 103 | diff --git a/1.txt b/1.txt 104 | index 5bc6c8d..5affb52 100644 105 | --- a/1.txt 106 | +++ b/1.txt 107 | @@ -17,5 +17,5 @@ 108 | 16 109 | 17 110 | 18 111 | -19 112 | +aa 113 | 20 114 | -- 115 | 2.9.2.windows.1 116 | ``` 117 | If this was the patch which Git created after running `git cherry-pick commit-4`and failed to apply the only chunk here, then Git will try to do _3 way merge_ by specify the base to be the `blob` `5bc6c8d` (left side - the version of `commit-2`), and merge between `blob` `5affb52` (right side - the version of `commit-3`) and the `blob` of our version of this file (`1.txt` in the patch from the example above). 118 | 119 | If Git fails during the _3 way merge_, then it means Git found conflicts, and he will do 2 things: 120 | * set the file `CHERRY_PICK_HEAD ` to point to the problematic commit we can't cherry-pick, which is `commit 4`. Why? I will answer this after the pseudo code. 121 | * __You__ need to resolve those conflicts. Good luck. How? The same way we resolve _merge conflicts_ while running `git merge`. After that, run `git cherry-pick --continue` because maybe there are more conflicts (Git let you resolve at most 3 conflicts at once). If everything goes well from here and no conflicts are found, then a new commit will be created: `commit-4` in the active branch. We are done! 122 | 123 | _End of pseudo code_ 124 | 125 | ### Multiple commits at once 126 | 127 | What if we want to cherry-pick multiple commits? For example: `git cherry-pick commit-2 commit-3 commit-4` ? Git does the same process over and over again from the most left commit to the most right commit in the command. 128 | The exciting part is if there were conflicts while applying `commit 3`, how Git will know where to go back after you resolve the conflicts? Well, that's easy, Git saved a reference to the problematic commit (`commit-2` in this example) inside the `CHERRY_PICK_HEAD` file. So after resolving the conflicts, Git know which it commits cherry-pick now and will move to the next commit in the command above (`commit-3` in this example). 129 | 130 | Same as if we want to: `git cherry-pick commit-1..commit-4`which means: cherry pick every commit from `commit 4` (`commit4` will be cherry-picked) until `commit 1` (`commit1` will __not__ be cherry picked). In other words: everything from `commit-4` to `commit-2`. 131 | 132 | ### Quiz 133 | 134 | 1. can I cherry-pick a commit in my branch? There can be 2 reasons this can fail -go to step 4 in the pseudo code. 135 | 136 | ----- 137 | 138 | ### Legal 139 | 140 | © Stav Alfi, 2017. Unauthorized use and/or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear 141 | credit is given to Stav Alfi with appropriate and specific direction to the original content. 142 | 143 | Creative Commons License "Git Cherry Picking by Stav Alfi" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 144 | Based on a work at https://gist.github.com/stavalfi/70ff71b3693a0eda6994550b91627af1. -------------------------------------------------------------------------------- /Introduction To Docker.md: -------------------------------------------------------------------------------- 1 | # Introduction to docker by Stav Alfi 2 | 3 | #### Topics 4 | 5 | 1. [Introduction](#introduction) 6 | 2. [What is a Docker?](#what-is-a-docker) 7 | 3. [Docker components](#docker-components) 8 | 9 | ![](https://www.docker.com/sites/default/files/Whale%20Logo332_5.png) 10 | 11 | The end of this article contains the [complete terms table](#complete-terms-table). 12 | 13 | --- 14 | 15 | ### Introduction 16 | 17 | In this article, we will define what docker is, and it's main components. 18 | 19 | ###### Prerequirements 20 | 21 | Basic knowledge about what is a compilation, unit tests, CI (Continuous integration) and CD (continuous deployment), virtual machines, cluster, and Linux. 22 | 23 | You can ignore any other phrase. 24 | 25 | ### What is a Docker? 26 | 27 | In short, Docker is a software for managing CI/CD for our application. It means, we no longer need to manually install our products after each build in the development/production environment. Docker does that by letting us install multiple _tiny_ operation systems (e.g., Ubuntu) on our virtual/physical machine, and each _tiny_ operation system will contain a single web application (Why we choose to dedicate the _tiny_ OS to a single application? we will cover the reasons later). 28 | 29 | By referring to _small_ operation system, we mean a smaller size of an operating system with fewer features than regular compared to installing an operating system on a virtual machine or our machine. How small can be an operating system in docker? So small it contains the minimal features for our web-app it can fully operate. For example, most web apps won't require the machine which they are installed on to contain some ubuntu packages as ping/git/maven and so on in production environment. 30 | 31 | ### Docker components 32 | 33 | ###### Docker engine 34 | 35 | _Docker deamon_ is the service in our machine (which is a part of a docker application). It is a process running on our machine and is responsible for creating/removing/updating those _tiny_ operation systems. The way we can communicate with him ( tell him what to do) is by a _docker CLI_ which we use to send commands to the docker daemon by a REST API he exposes. In short, the docker daemon is the backend, and the docker CLI is the frontend. Together they are called _docker engine_. Each operating system that you want to install small operating systems on must have a docker engine installed. 36 | 37 | ###### Docker image 38 | 39 | When you want to install a web application on an OS, first you need an OS and then installing the requirements software for the web application you would like to finally install and then configure those software and maybe the OS you are installing. Finally, you can install your web application. 40 | 41 | This process is too long, manual and can fail by human errors. A better way is to do it once (or describe it by commands - will be explained later) and save that OS we built with all those software and our web applications to our disk so we can use that save later again. Meaning if we use that save again, we will load the OS in the same state it was when we created that save. 42 | 43 | The state of an OS in a specific time is called _snapshot_ and the saved snapshot is called _docker image_. We can create multiple instances of the different/same docker image in the same OS docker engine is installed. 44 | 45 | Docker let us create an image from an image. Meaning, we can run an image and change as we like anything in that _tiny_ OS and then create a new image from the current snapshot of that _tiny_ OS. We just run. 46 | 47 | ###### Docker repository 48 | 49 | Each image is dedicated to a single web application. It is possible that you would like to create multiple images containing the same web application with different settings or different versions of software your web application need or remove/add/change settings of the OS for different use cases. All in all, you may find your self in a situation you have multiple images for the same web application. Docker let us use _tags_ to differentiate multiple different images which are dedicated to the same web application. A tag is an additional string which will be presented alongside the name of the image. 50 | 51 | Multiple Images with the same name but contain different tags are called _docker repository_. 52 | 53 | ###### Docker registery 54 | 55 | Is it possible and highly recommended to share images between users. There are _places_ where one can upload images, manage them and download others. This kind of place is called a _docker registery_. Docker registry is a service which manages docker repositories. 56 | 57 | Today there is an image for most of the web applications in multiple versions. It means multiple users created an image dedicated to the same web application but with some changes in the web applications or the OS that web application is installed on. It means different users manage different docker repositories for the same image. 58 | 59 | To download and run images on our OS, you can enter one of many docker registries out there (e.g., https://hub.docker.com) 60 | 61 | Search an image by name, download and run it! (How? Will be covered in the different article). 62 | 63 | ###### Docker container 64 | 65 | When we "running" an image, we are creating some "virtual machine" which load that image. An image is a snapshot of an operating system, so all we need to do is to run that image somewhere. _Docker container_ is the tool which runs an image. Containers share some similarities with virtual machines. They are running OS, and you can connect to its shell and run any script you want. 66 | 67 | Docker containers are fast. They communicate with the host OS kernel. We can configure multiple containers to be visible to one another while still invisible from the outside world. We choose which ports we open for communicating containers in the same host the docker engine is installed (It is the one who manages images and containers) and which ports will be visible to the outside world. We can relate OS ports to specific container ports. It means when we try to reach `localhost:X`, we are reaching container1_ip:X. 68 | 69 | We can also restrict the number of resources which will be used by a container from the host OS. But this will be discussed in a future tutorial. 70 | 71 | The best practice is to load one web application in each container. From what we described, we can load the same image multiple times to have a cluster for example. (a Cluster is a group of physical/ virtual machines that operate as one). 72 | 73 | Check swarm for more information about docker cluster management. 74 | 75 | 76 | 77 | ###### Dockerfile 78 | 79 | Another way to create an image is by describing what we want it to look like using individual commands/instructions in a file called _dockerfile_. Then we create an image from that docker file. 80 | 81 | The `dockerfile` is divided into 3 parts: 82 | 83 | 1. A _base image_. It can be a simple ubuntu image or an IIS image which on top of that we will describe (by dockerfile instructions) what we want to change in it. You can use any image you want. It is a requirement to tell what the base image you will use is explicit. This instruction is called ```FROM ```. 84 | 2. Additional and optional instructions that responsible for changing the state of the base image. 85 | 3. Optional instruction responsible for running a web application this image is dedicated to. This command can be overridden when we "start and run" the image. It will run as soon as the image is "running". This instruction is called ```CMD command param1 param2``` (It is not the windows CMD). 86 | 87 | The `dockerfile` is transformed into an image using a temporary container which runs the `dockerfile` and saves the container's snapshot to an image. 88 | 89 | 90 | ![](https://i.imgur.com/U4GnCD8.jpg) 91 | 92 | 93 | ###### Docker service 94 | 95 | There is a need to control multiple containers which all run the same image (for cluster management). A _docker service_ is a couple of containers running the same image with a defined state. Docker let us describe the desired state of service: The amount of _replicas_ (multiple containers running the same image), minimum resources that a container must have for running a replica, what is the image we are trying to deploy and so on. The description will be written in a yml file written in `yaml` language: 96 | 97 | ```yaml 98 | services: 99 | web: 100 | image: stavalfi/myimage1:latest 101 | deploy: 102 | replicas: 5 103 | resources: 104 | limits: 105 | cpus: "0.1" 106 | memory: 50M 107 | restart_policy: 108 | condition: on-failure 109 | ports: 110 | - "80:80" 111 | ``` 112 | 113 | Who is deploying and managing (ensuring that the state of the service will be as described in the `yml` file) the service/s? The `docker-engine`. More specifically, an existing and running _swarm_. Before we talk about swarms, we need to understand how to describe an application which contains multiple services using yaml. 114 | 115 | ###### Docker stack 116 | 117 | Docker service is described using yml file. We can describe multiple services in the same file and this is called _docker stack_: 118 | 119 | ```yaml 120 | services: 121 | web: 122 | image: stavalfi/myimage1:latest 123 | deploy: 124 | replicas: 5 125 | ports: 126 | - "80:80" 127 | networks: 128 | - webnet 129 | visualizer: 130 | image: dockersamples/visualizer:stable 131 | ports: 132 | - "8080:8080" 133 | networks: 134 | - webnet 135 | redis: 136 | image: redis 137 | ports: 138 | - "6379:6379" 139 | volumes: 140 | - /home/docker/data:/data 141 | deploy: 142 | placement: 143 | constraints: [node.role == manager] 144 | networks: 145 | - webnet 146 | networks: 147 | webnet: 148 | ``` 149 | 150 | Here we are describing multiple services' desired state: _web_, _visualizer_, _redis_ (those are only the name we chose to refer to those services). 151 | 152 | ###### Docker swarm 153 | 154 | > **Definition 1.11.** ___Docker container orchestration___ is a service which able to manage containers in different virtual/ physical machines. It is responsible for running/stopping/suspend containers and also preserves a state that is defined for every service in a stack it manages. 155 | 156 | > **Definition 1.12.** ___Docker swarm___ is a docker container orchestration service from docker company. 157 | 158 | In simple words, docker swarm is a stack manager which ensure that the state described by the yml file will preserve. Swarm consists of multiple nodes (one or more virtual/ physical machines). Each node can be a _worker node_ or _manager node_. The creator of the swarm is a manager and also the _leader node_. He can promote or provoke nodes to worker/manager degree. 159 | 160 | > **Definition 1.13.** ___Task___ is a request from a worker node to run container with a specific image. The task is in a _running_ state only after the container is in a _running_ state. In case of any problem with the container, it states will also change and will cause the task to change its state and send it's new state to one of the managers to examine the problem. 161 | 162 | To examine a docker task let's describe an example where a container is down, then it's task is terminated and as a result, one of the managers will automatically create a new task with the same image in one of the nodes in the swarms which can be assigned with new tasks. The managers or the leader can assign the task to a node in any type, even them selfs (but they will prefer to assign a task to a worker node). 163 | 164 | > **Definition 1.14.** ___Worker node___ is a node who does not have any permission to modify or examine the state of the swarm nor see the nodes in it. It has a docker engine installed, and it checks with one of the managers for new tasks or gets requests from the swarm's load balancer to a specific container in it. 165 | 166 | > **Definition 1.15.** ___Manager node___ is a worker node which promoted by the leader to a manager degree. It can change the swarm state; stop/run/rm services in the swarm. The manager assigns tasks to nodes in the swarm (Including himself if this node is configured to run tasks) to preserve the state of a service in a swarm. Manager node checks the health of worker nodes and the status of all the tasks he assigned to examine any change. 167 | 168 | > **Definition 1.16.** ___Leader node___ is the node which created the swarm. He gave full privilege to control the swarm state same as a manager node. It also can Promote worker nodes to manager nodes or vice versa. 169 | 170 | ###### More about swarm services 171 | 172 | Services are only running inside a swarm. There are two options to deploy a service in a swarm: 173 | 174 | 1. _Replicated services model_ - We explicitly specify how much replicas will be running inside a swarm. It means that if he wants 5 replicas for image `stavalfi/projecty:latest`, the swarm managers will try to create 5 tasks in the swarm. They will try to balance the number of tasks created in each node, depending on how much running tasks it run at the moment. 175 | 2. _Global services model_ - Each service will be deployed in all the swarm's nodes. This option is suitable for deploying a monitoring/anti-virus/.. services. 176 | 177 | For every service, we can specify conditions which every node want to run a task need to fulfill them. For example, we can deploy service only in manager nodes. Also, we can specify how many minimum and maximum resources will be used by each service's container. It means that if a node does not have the minimum resources for running that container as we explicitly specify, then that task won't send to that node. If a no node can fulfill all the conditions for a service, all its tasks won't start; the task will be in a _pending_ state. 178 | 179 | The following image is from [docker docs](https://docs.docker.com/engine/swarm/how-swarm-mode-works/services/#services-tasks-and-containers): 180 | 181 | ![](https://docs.docker.com/engine/swarm/images/service-lifecycle.png) 182 | 183 | 184 | 185 | --- 186 | 187 | ### Complete terms table 188 | 189 | > **Definition 1.1.** ___Docker deamon___ it is a process running on our machine and is responsible for managing containers and images. 190 | 191 | > **Definition 1.2.** ___Docker CLI___ is a client tool we can use from the command line to send commands to the REST API of the docker daemon in the same operating system to tell him what we want him to do. 192 | 193 | > **Definition 1.3.** ___Docker engine___ is the docker deamon and the docker CLI. 194 | 195 | > **Definition 1.4.** The state of an OS in a specific time is called _snapshot_ and the saved snapshot is called ___docker image___. 196 | 197 | > **Definition 1.5.** ___Docker tag___ is describing the version of an image (Not only numeric version). 198 | 199 | > **Definition 1.6.** Multiple Images with the same name but contain different tags are called ___docker repository___. 200 | 201 | > **Definition 1.7.** ___Docker registery___ is a service which provides a way to manage our docker repositories and let us download different docker images from different users. 202 | 203 | > **Definition 1.8.** ___dockerfile___ is a file described by special instractions/commands to define an image. 204 | 205 | > **Definition 1.9.** ___Docker service___ is a couple of containers running the same image with a defined state. 206 | 207 | > **Definition 1.10.** ___Docker stack___ is a couple of docker services. 208 | 209 | > **Definition 1.11.** ___Docker container orchestration___ is a service which able to manage containers in different virtual/physical machines. It is responsible for running/stopping/suspend containers and also preserves a state that is defined for every service in a stack it manages. 210 | 211 | > **Definition 1.12.** ___Docker swarm___ is a docker container orchestration service from docker company. 212 | 213 | > **Definition 1.13.** ___Task___ is a request from a worker node to run container with a specific image. After the container is up, the task is running, and any change in the container will cause the task to change its state and send it's new state to one of the managers to examine the problem. 214 | 215 | > **Definition 1.14.** ___Worker node___ is a node who does not have any permission to modify or examine the state of the swarm nor see the nodes in it. It has a docker engine installed, and it checks with one of the managers for new tasks or gets requests from the swarm's load balancer to a specific container in it. 216 | 217 | > **Definition 1.15.** ___Manager node___ is a worker node which promoted by the leader to a manager degree. It can change the swarm state; stop/run/rm services in the swarm. The manager assigns tasks to nodes in the swarm (Including himself if this node is configured to run tasks) to preserve the state of a service in a swarm. Manager node checks the health of worker nodes and the status of all the tasks he assigned to examine any change. 218 | 219 | > **Definition 1.16.** ___Leader node___ is the node which created the swarm. He gave full privilege to control the swarm state same as a manager node. It also can Promote worker nodes to manager nodes or vice versa. 220 | 221 | 222 | ------------------ 223 | 224 | ### Legal 225 | 226 | © Stav Alfi, 2017. Unauthorized use or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to Stav Alfi with appropriate and specific direction to the original content. 227 | 228 | Creative Commons License "Introduction to docker by Stav Alfi" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 229 | Based on a work at https://gist.github.com/stavalfi/eea616c2aaf5299a84c718a77cfe8668. -------------------------------------------------------------------------------- /Introduction To Git.md: -------------------------------------------------------------------------------- 1 | # Introduction to Git by Stav Alfi 2 | 3 | 4 | 5 | ### Topics 6 | 7 | 1. [Introduction](#introduction) 8 | 2. [Repository structure](#1-repository-structure) 9 | 3. [What are Branches](#2-what-are-branches) 10 | 4. [Merging & Conflicts](#3--merging--conflicts) 11 | 5. [Rebase & Going deeper](#4-rebase--going-deeper) 12 | 13 | ###### Commnads: 14 | 1. [Areas](#areas) 15 | 2. [Branchs](#branchs) 16 | 3. [Merges and rebases](#merges-and-rebases) 17 | 4. [Remote](#remote) 18 | 5. [Stash](#stash) 19 | 6. [Logs](#logs) 20 | 21 | The end of this article contains the [complete terms table](#complete-terms-table). 22 | --- 23 | 24 | ### Introduction 25 | 26 | The tutorial is intended for programmers that want to dive deep and understand what is going on behind the scene. After reading and practicing you should be able to manipulate and understand more advanced articles online about other topics that are not mentioned here. 27 | 28 | You will learn familiar concepts and fully understand their definitions. 29 | 30 | __Prerequirements__ 31 | 32 | No requirements. 33 | 34 | ### Tutorial 35 | 36 | 37 | #### 1. Repository structure 38 | 39 | Git is a source control system, and it builds on areas to have better control about what you are doing. 40 | 41 | 42 | 43 | > **Definition 1.1.** _**Working space** is the main folder of your local repository. It contains tracked/untracked files/directories by git. 44 | > Files/directories that Git is tracking on will be called as tracked. 45 | > Files/directories that Git is not tracking on will be called as untracked. 46 | > Files/directories that Git is tracking on and those files/directories modified will be called as Modified but not staged_. 47 | 48 | Git does not track on files or directories if you don't tell him to. To tell Git to start tracking on a file to look for future changes or to copy the changes you did to a specific tracked file to the stages area: 49 | `git add `. Then all the changes will be added to the staged area to be committed later. 50 | To commit: `git commit -m `. 51 | 52 | 53 | > **Definition 1.2.** _**Index** is a file under the `.git` folder in your working directory that contains all the changed you did for tracked files/directories under the working directory. We also refer it as the **staged area**._ 54 | 55 | > **Definition 1.3.** _The working space is changing over time. A group of changes that you want to save and go back to in the future is called a **commit**. Commit is a file that contains changes in your project compared to the last change you saved and also contain an ID called **SHA-1**._ 56 | 57 | Commits are created from changes in the stage area. 58 | They also contain the SHA-1 of the commit that created before them on the same branch, Who is the commit's creator and some other details. You can look over all the local commits by running `git log`. 59 | 60 | ![commits](https://i.stack.imgur.com/IY4PK.png) 61 | 62 | 63 | > **Definition 1.4.** _**Local repository** refers to all the commits in your local project._ 64 | 65 | By committing some changes over time, you will create a graph that each node is a commit that looks at his _father_ commit. If you want to go back to a specific commit, Git will rebuild the repository history again but will stop at the commit that HEAD is pointing to. 66 | (We will Define and talk more about what HEAD means later on). 67 | 68 | 69 | #### 2. What are Branches 70 | 71 | To let multiple developers work and change the same repositories concurrently and independently, we use branches. 72 | 73 | > **Definition 1.5.** _**Branch** is the pointer (can and will be reassigned) to a specific commit. They contain the SHA-1 of the commit they are pointing to. `HEAD` usually is a pointer to the current branch you are working on, and we refer the branch that the `HEAD` is pointing to be the **working branch**_ 74 | 75 | When you are committing new commit, a new commit will be created on top of your branch. That means the working branch to be now pointing to the new commit (The new commit is pointing to the old commit, so no commits are lost by this process). 76 | A branch stored in a file under the `.git\ref` folder. There are 2 types of branches: Locals and remotes (We will talk about remote branches later). The locals are located under the `heads` folder. 77 | When You create a new repository, you will be assigned the `master` as the main branch. 78 | You can create multiple branches that will point to any commit you choose by running `git checkout -b `. To change the branch that `HEAD` is pointing to, run `git checkout `. 79 | 80 | branch master 81 | / 82 | A1 <--A2 <--A3 <--A4 83 | \ 84 | branch testing <- HEAD 85 | 86 | 87 | __Why do we need branches?__ 88 | 89 | For instance, when we will create a new commit under the testing branch, the testing branch will be pointing to the new commit but the master branch will not change. 90 | 91 | branch master 92 | / 93 | A1 <--A2 <--A3 <--A4 <--A5 94 | \ 95 | branch testing <- HEAD 96 | 97 | Now changing `HEAD` to point to the master branch and commit again, the testing branch won't change but only the master branch. 98 | 99 | A6 <- branch master <- HEAD 100 | / 101 | A1 <--A2 <--A3 <--A4 <--A5 102 | \ 103 | branch testing 104 | Now we have a nonlinear history. In other words, there is more than one commit that points to commit `A3`. 105 | 106 | After we tested some code in the testing branch, we want to update our master branch with our changes (In case the master branch is the deployment branch, and the testing branch is the development branch). 107 | 108 | #### 3. Merging & Conflicts 109 | 110 | A1--A2--A3--A4 (branch development) 111 | \ 112 | A11--A12 (branch master) 113 | 114 | You created a branch for development and finished with some features. Currently, you are in the _master_ branch, and you want to update the _master_ branch with the commits: _A2, A3, A4_. By running `git merge development`, you are creating a new commit in the master branch _A13_ that contain the __changes that the _master_ branch doesn't have and the _development_ branch have__. 115 | 116 | A1--A2--A3--A4 (branch development) 117 | \ \ 118 | A11--A12-----A13 (branch master) 119 | 120 | Notice that the _master_ branch is now looking at commit _A13_ and commit _A13_ is pointing to both _A4_ and _A12_. That's a particular case in git where a commit is pointing to more than one commit. 121 | 122 | The problem with merges that they make a _non-linear history_. 123 | 124 | > **Definition 1.6** _**Non-linear history**_ is a history that contains a commit that points to more than one commit. It makes the history log difficult to look at and manage it. Try to avoid it as much as you can. 125 | 126 | > **Definition 1.7** _**merge commit**_ is a commit created by a merge and usually points to multiple commits. 127 | > 128 | __Conflicts__ 129 | 130 | Sometimes the merge operation doesn't go so well because: 131 | 1. Both commits (_A4_ and _A13_) updated or created the same file __after__ the closet ancestor commit _A1_. 132 | 2. (?) 133 | 134 | In such cases, Git will let you solve the conflicts by showing you both file versions in that file and let you decide which version you want. When you finish, stage your changes and then commit. 135 | 136 | 137 | #### 4. Rebase & Going deeper 138 | 139 | An alternative in most cases of merging will be `rebase`. It will recreate the history from a specific point to a specific point. 140 | We had the following history: 141 | 142 | A1--A2--A3--A4 (branch development) 143 | \ 144 | A11--A12 (branch master) 145 | 146 | We want to add the commits: _A2, A3, A4_ to branch _master_. First, go to _development_ brach, the branch you want to rebase and run `git rebase master`- That will recreate commits _A2, A3, A4_ in master branch and set branch development to point the copy of commit _A4_. 147 | 148 | ``` 149 | A1 (branch master) 150 | \ / 151 | A11--A12--A2`--A3`--A4` (branch development) 152 | ``` 153 | 154 | __What does rebase do__ 155 | 156 | Attempting to rebase branch _development_ on brach _master_ will start copy all the commits needed one by one - From the child of the closest ancestor of both branches to the top commit in branch _development_. The copying of each commit is _Cherry-pick_. When the `rebase` is starting, you are entered to _detached head_ state, and each commit __will try to__ cherry-pick on top of branch _master_. 157 | 158 | > **Definition 1.8** _**Detached head state**_ occurs when the _HEAD_ is not pointing to a local branch. Even if you are pointing to a remote branch, you are still in that state. Each new commit will be on top of that commit _HEAD_ is pointing to. Not any of your branches will point to the new commits you did in _detached head state_. Git will give those new commits 30 days until they will be removed automatically. 159 | 160 | In case of a conflict happened by the cherry-pick, you need to solve it and then run `git rebase --continue` or in case you want to stop the rebase, run `git rebase --abort`. By the time each cherry-pick ends, the new commit is identical to the old commit but with a new SAH-1. 161 | 162 | Caution: Rebase does not know how to deal with merge commits. 163 | When using rebase on a branch that had a _merge commit_, Git will ignore that commit and _cherry-picking_ each path that the merge commit is pointing to. The order of which path it will _cherry-picking_ is random unless you specify it your self. 164 | 165 | ______ 166 | 167 | 168 | ### Most Asked Questions 169 | 170 | __Q:__ My push failed because someone pushed before I did. Why did it fail? 171 | 172 | __A:__ The push is not _fast forward_. Consider the following case where you try to push to a branch with the same name as the branch you are working on right now, `B`. `B` point to commit `2` and `origin/B` points to commit `1` (You didn't push your branch yet, so the server's branch doesn't have the up to date commits). 173 | Also, commit `2` point to commit `1`: 174 | 175 | ``` 176 | 2 (B) 177 | \ 178 | 1 (origin/B) 179 | ``` 180 | Now your teammate push (before you pushed) to branch `B` but you still didn't `fetch` so you don't know it yet. The __server__ graph is: 181 | 182 | ``` 183 | 3 (B) 184 | / 185 | 1 186 | ``` 187 | 188 | Now you are trying to push but fail because your push is not _fast forward_. Why? First, we should know that if Git allowed us to push in this situation, the result could be: 189 | 190 | ``` 191 | 2 (B) 3 (B is not pointing to this commit anymore!! BAD) 192 | \ / 193 | 1 194 | ``` 195 | 196 | Secondly, _fast forward_ mean we could do merge/push /pull without losing commits. In other words, There must be a link from the first commit we are trying to push to the commit which the branch in the server is pointing to. As we see in this example, there is no such link. Linking means we can go from commit `2` to commit `3`. (Invalid link is going from commit `1` to commit `2` or `3` or going from commit `2` to commit `3`). 197 | 198 | The solution is to `fetch` on our local machine. The following graph show to result after `git fetch`: 199 | 200 | ``` 201 | 2 (B - HEAD) 3 (origin/B) 202 | \ / 203 | 1 204 | ``` 205 | Then we must merge or rebase. The following graph show to result after `git merge origin/B`: 206 | 207 | ``` 208 | 4 (B - HEAD) 209 | / \ 210 | 2 3 (origin/B) 211 | \ / 212 | 1 213 | ``` 214 | Then our push will be _fast forward_ unless someone pushed before us again. 215 | 216 | --- 217 | 218 | __Q:__ I’m in detached head state. What do I do? 219 | 220 | __A:__ It is highly recommended that you create a new branch where you are unless you are only watching the working directory at this commit. The definition for _Detached head state_ : 221 | 222 | > **Definition 1.7** _**Detached head state**_ occurs when the _HEAD_ is not pointing to a local branch. Even if you are pointing to a remote branch, you are still in that state. Each new commit will be on top of that commit _HEAD_ is pointing to. Not any of your branches will point to the new commits you did in _detached head state_. Git will give those new commits 30 days until they will be removed automatically. 223 | 224 | --- 225 | 226 | __Q:__ How do I edit a friend’s code written in a specific time in history? 227 | 228 | __A:__ Tell him to push his branch and then you `fetch` so you can see his most up to date work at his branch. You can't `checkout` his branch without creating a new branch and **then commit new changes** because if git approved it, his branch in the server would point to new commit without you doing any explicit `push`. 229 | 230 | 231 | 232 | Comming soon: Everything about remotes. 233 | 234 | --- 235 | 236 | ### Most used commands 237 | __Switching between areas, changing your working directory files and branches__ 238 | 239 | #### Areas 240 | * _Untracked_ , _Modified but not staged_ (_Working directory_) 241 | * _Staged_ (_Index_) 242 | * _Commited_ (_local repository_) 243 | * _Online repository_ 244 | 245 | ![areas in git](http://interactionprototyping.github.io/exercises/images/github/git-stages.svg) 246 | [Picture source: interactionprototyping.github.io](http://interactionprototyping.github.io/exercises/) 247 | 248 | 1. `git add ` - file A switch from _untracked_ to _staged_ or from _modified but not staged_ to _staged_. It depends where file A was before running the command. 249 | 2. `git commit -m ` - Create new commit from the files in the _staged_ area. In case you need more than one word in the text, use "..your message..". 250 | 3. `git commit -am ` - Create new commit from the files in the _Modified but not staged_ and _staged_ areas. In case you need more than one word in the text, use "..your message..". 251 | 4. `git reset HEAD~` - Remove your last commit and delete everything from the _stage_. 252 | 5. `git reset -- soft HEAD~` - Remove your last commit and put it in the _stage_ and does delete the current files on _stage_. 253 | 6. `git reset` - moving everything from the _stage_ to _modified but not staged_. If a file was _untracked_ before it was inside the _stage_, then it will be _untracked_ again. 254 | 7. `git commit --amend` - Remove your last commit and moving the last commit to _stage_ and doesn't delete the current files on _stage_. 255 | 8. `git reset HEAD ` - move file A from _stage_ to the area it was before (tracked and committed by git or not tracked by git). 256 | 9. `git checkout -- ` - If file A existed in the last commit, then file A will be now in the working directory as it was in the last commit. If not, the file will be as it was in the _stage_ phase. 257 | 258 | #### Branchs 259 | 260 | 1. `git checkout ` - Git changes your working directory to be as it was in commit with SHA-1 that equals the value of branch A. 261 | 262 | Then the value of `HEAD` changes to the name of branch A (which is "`A`"). Also, if `A` is the name of the branch in the remote server (for example _origin/A_), and you want to see him (or add commits to him), this command creates a new branch, called, `A` (if it doesn't exist already) and now `HEAD` is pointing to `A`. 263 | 2. `git branch -d ` - Remove branch A from your local repository. No changes occur to your working directory. 264 | 3. `git branch ` - Create a new branch with the name A in your local repository with the value of the last commit's SHA-1 ("ID") you committed. 265 | 4. `git checkout -b ` - Create a new branch in your local repository with the name A with the value equals to B. Then change HEAD's value to A. 266 | 5. `git checkout -b :` - Creating a new branch in your local repository with the name `A` that has the same value as branch `C`. 267 | 268 | Then `HEAD` is referencing now to `A` and your working directory will be changed to the commit that branch A points to. 269 | 6. `git checkout --track :`- shortcut of the last command but now the new branch will be called `C`. 270 | 7. `git checkout ` - change your working directory to look as it was in commit `A`. Change `HEAD`'s value to A's SHA-1. (You are now _Deteched head_ state and also `HEAD`'s value is an SHA-1 and not a reference to existing branch). 271 | 272 | #### Merges and rebases 273 | 274 | 1. `git merge ` - Create a new commit _B_ in the top of the working branch (where _HEAD_ is pointing to). `B` points to both the last commit _HEAD_ pointed too, and the top commit in branch _A_. Commit _B_ contains the changes in both commits he points to. This command creates a _non linear_ history. Try to use `rebase` command as an alternative. 275 | 2. `git rebase `- create a commit _b1_ to be at the top of the _working branch_, commit _a1_ to be the top of branch _A_ and commit _c1_ to be the closest ancestor of both _b1_ and _a1_. Copy all the commits from _b1_ to the child of _c1_ in the _working branch_ to the top of branch _A_. Rebasing does not know how to deal with _non-linear history_ if you don't specify how. In case you are rebasing a merge commit (a commit that points to multiple commits), then the merge-commit will not be copied during the `rebase` process. It means that Git will remove the merge-commit. 276 | 277 | The path order that Git will copy will be random. See more details in the tutorial. 278 | 279 | #### Remote 280 | 281 | 1. `git clone ` - Creating a local directory with the repository files and directories. Also does `git remote add shortRemoteRepositoryNameB A` (Command 2). Creating a local branch name master that points to the commit where shortRemoteRepositoryNameB/HEAD is pointing (The HEAD in the server). 282 | 2. `git remote add ` - A will be a shortcut to B. 283 | 3. `git fetch ` - Update all your local repository to have the most up-to-date commits/branchs/.. from A. It does not change anything in your working directory and __does not__ create local branches with the same name as the remote branches and this command will not change your local HEAD. 284 | 4. `git push ` - Asking the remote repository to add to remote branch B your commits in local branch B that it doesn't have. Conditions: (a) Changing the value of remote branch B should be _fast forward_. (b) Your repository must have a copy of the most up to date remote branch B. 285 | 5. `git pull` - Same as `git fetch` and `git merge @{u}`. The latter means merging __only__ your working branch with the remote branch that has the same name. If _fast forward_ occurred, then your local branch is not pointing to the same commit as the remote branch with the same name. If not, your local branch that involved with the merge will point to the new merge commit and _HEAD_ will. __It is recommended to use `git pull` to do only _fast forward___. 286 | 6. `git push --delete ` - Deleting branch B the remote server but not local branch B (if it exists). 287 | 288 | #### Stash 289 | 290 | 1. `git stash` - Its goal to save the work that we did not commit. In more details, Git will save the index content in a particular stack with the changed made to known files by git. This command will create two commits: 291 | * The first contains the content of the index file. 292 | * The second contains the content of the changes we made to all of the files known by Git. 293 | 294 | The second commit points to the first commit and the first commit points to the commit where the active branch is pointing to. After that, Git will remove any changes we did to all the known files by Git since the last commit and also delete the content of the index file. 295 | 296 | For each additional stash, the saved data will be pushed to the stack so the older stashes' indexes will increase by one. Also, the commits created by the last stash will be removed, and new ones will be created with the same logic. 297 | 298 | 2. `git stash list` - show list of all stash exist in our stack. the newest stash is `0` and the oldest stash have the biggest number - equal to the number of active/saved stashes we made `-1`. 299 | 3. `git stash clean` - empty the stash stack. 300 | 4. `git stash pop` - try to pop out the last stash was saved in the stack by adding the changes from the index stash commit to our index and the changes from the second commit to our working directory. There may be conflicts need to be taken care of. 301 | 5. `git stash pop stash@{i}` - try to pop the stash saved in the stack with index `i`. If there are no conflicts, remove the poped stash from the stack. 302 | 6. `git stash apply stash@{i}` - `try to pop the stash saved in the stack with index. 303 | 304 | 305 | 306 | #### Logs 307 | 308 | 8. `git diff ` - Print the changes of file A in the _tracked but modified_ comparing to file A in the last commit. 309 | 9. `git diff -- cached ` - Print the changes of file A in the _staged_ comparing to file A in the last commit. 310 | 10. `git diff ` - print the differences between A and B. 311 | 11. `git remote -v` - print the short names of the remote repositories' URLs. 312 | 313 | With Git, you can easily edit the log output as you wish. 314 | There are some ready-made logs created by other. Go to your home directory and edit the file `.gitconfig`. Add the following lines to the end of the file.: 315 | 316 | [alias] 317 | lg = !"git lg1-specific --all" 318 | lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' 319 | 320 | Now by running: `git lg` = `git lg1`, `git lg2`, `git lg3` you can see all your branches and commits throughout a graph. 321 | 322 | --- 323 | ### Complete terms table 324 | 325 | > **Definition 1.1.** _**Working space**_ is the main folder of your local repository. It contains tracked/untracked files/directories by git. 326 | > Files/directories that Git is tracking on will be called as tracked. 327 | > Files/directories that Git is not tracking on will be called as untracked. 328 | > Files/directories that Git is tracking on and those files/directories modified will be called as Modified but not staged. 329 | 330 | > **Definition 1.2.** _**Index**_ is a file under the `.git` folder in your working directory that contains all the changed you did for tracked files/directories under the working directory. We also refer to it as the _**staged area**_. 331 | 332 | > **Definition 1.3.** The working space is changing over time. Each important change that you want to save and go back to in the future called a **commit**. Commit is a file that contains changes in your project compared to the last change you saved and also contain an ID called _**SHA-1**_. 333 | 334 | > **Definition 1.4.** _**Local repository**_ refers to all the commits in your local project. 335 | 336 | > **Definition 1.5.** _**Branch**_ is the pointer (can and will be reassigned) to a specific commit. They contain the SHA-1 of the commit they are pointing to. `HEAD` usually is a pointer to the current branch you are working on, and we refer the branch that the `HEAD` is pointing to be the **working branch** 337 | 338 | > **Definition 1.6** _**Non-linear history**_ is a history that contains a commit that points to more than one commit. It makes the history log challenging to look at and manage it. Try to avoid it as much as you can. 339 | 340 | > **Definition 1.7** _**merge commit**_ is a commit created by a merge and usually points to multiple commits. 341 | 342 | > **Definition 1.8** _**Detached head state**_ occurs when the _HEAD_ is not pointing to a local branch. Even if you are pointing to a remote branch, you are still in that state. Each new commit will be on top of that commit _HEAD_ is pointing to. Not any of your branches will point to the new commits you did in _detached head state_. Git will give those new commits 30 days until they will be removed automatically. 343 | 344 | ------------------ 345 | 346 | ### Legal 347 | 348 | © Stav Alfi, 2017. Unauthorized use or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear 349 | credit is given to Stav Alfi with appropriate and specific direction to the original content. 350 | 351 | Creative Commons License "Introduction to Git by Stav Alfi" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 352 | Based on a work at https://gist.github.com/stavalfi/1020abe20960c2daf215410da56250eb. 353 | -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 1 - What is a java stream.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 1 - What is a Java stream? 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Basic operations](#chapter-1-basic-operations) 8 | 3. [Operation types](#chapter-2-operation-types) 9 | 4. [Conclusion](#conclusion) 10 | 11 | ### Introduction 12 | 13 | A Java stream is a collection of elements that can be queried in a declarative way by a pipeline. 14 | 15 | > **Definition 1.1.** _**Pipeline**_ is a couple of methods that will be executed by a specific order. 16 | 17 | By query, we mean that some \(sometimes all\) operations in the pipeline will do something with each element in the source collection and calculate with all the elements, that successfully survived all the pipeline, a new value or a collection. 18 | 19 | ### Chapter 1: Basic operations 20 | 21 | Some of the basic operations that a pipeline can have are the following: 22 | 23 | --- 24 | 25 | | `void forEach(Consumer action)` | 26 | | :--- | 27 | | The _**forEach**_ method will run _action_ function on each element in the stream. | 28 | 29 | ```java 30 | // example: 31 | 32 | // create the collection 33 | List collection1= Arrays.asList(1,2,3); 34 | 35 | // create new stream from collection1 36 | Stream stream1= collection1.stream(); 37 | 38 | // print each element in stream1 39 | stream1.forEach((Integer x)-> System.out.println(x)); 40 | 41 | // the above is equivalent to: 42 | // collection1.stream().forEach(System.out::println); 43 | 44 | // output: 45 | // 1 46 | // 2 47 | // 3 48 | ``` 49 | 50 | --- 51 | 52 | | ` Stream map(Function mapper)` | 53 | | :--- | 54 | | The _**map**_ method is meant to create from each element in the stream a new element. The type of the new element can be different from the source element. This method will not cause the stream to do anything. In each pipeline, we need a method that will make everything run, for example - the _forEach_ method as we saw. | 55 | 56 | ```java 57 | // example: 58 | 59 | // create the collection 60 | List collection1= Arrays.asList(1,2,3); 61 | 62 | // create new stream from collection1 63 | Stream stream1= collection1.stream(); 64 | 65 | // create new stream with the integers: 5,6,7 66 | // Note: we created new values instead of changing collection1's values. 67 | Stream stream2= stream1.map((Integer x)->x+4); 68 | 69 | // each stream object has the same methods 70 | stream2.forEach(System.out::println); 71 | 72 | // the above is equivalent to: 73 | // collection1.stream().forEach(System.out::println); 74 | 75 | // output: 76 | // 1 77 | // 2 78 | // 3 79 | 80 | collection1.stream() 81 | .map((Integer x)->"hi"+x) 82 | .forEach(System.out::println); 83 | 84 | // output: 85 | // hi1 86 | // hi2 87 | // hi3 88 | ``` 89 | 90 | --- 91 | 92 | | `Stream filter(Predicate predicate)` | 93 | | :--- | 94 | | The _**filter**_ operation will determine for each element in the stream if that element will stay or not. The method will run on each element in the stream and check using a condition specified in the _predicate_ function if the element should be in the next stream. The next stream will contain all the elements from the last stream that _predicate_ return true for them. | 95 | 96 | ```java 97 | // example: 98 | 99 | // create the collection 100 | List collection1= Arrays.asList(1,2,3); 101 | 102 | // create new stream from the collection 103 | collection1.stream() 104 | .filter((Integer x)-> x>1) 105 | .forEach(System.out::println); 106 | 107 | // output: 108 | // 2 109 | // 3 110 | ``` 111 | 112 | | `Stream peek(Consumer action)` | 113 | | :--- | 114 | | _**Peek**_ will run an action on each element of the stream and will return a stream containing the same elements. This operation is mainly to support debugging. For example, we can print the elements after each operation in the pipeline to see how the stream is calculating the elements. Also, it can be used for _side effects_. | 115 | 116 | ```java 117 | // example: 118 | 119 | Arrays.asList("aaa","bbb") 120 | .stream() 121 | .filter((String str1)->str1.contains("a")) 122 | .peek((String str1)-> System.out.println(str1)) 123 | .map((String str1)->str1.concat("ccc")) 124 | .forEach((String str1)-> System.out.println(str1)); 125 | 126 | // the above is equivalent to: 127 | //Arrays.asList("aaa","bbb") 128 | // .stream() 129 | // .filter((String str1)->str1.contains("a")) 130 | // .peek(System.out::println) 131 | // .map((String str1)->str1.concat("ccc")) 132 | // .forEach(System.out::println); 133 | 134 | // output: 135 | // aaa <- printed by peek 136 | // aaaccc <- printed by forEach 137 | ``` 138 | ### Chapter 2: Operation types 139 | 140 | We can see that in every pipeline there are 2 types of operations: 141 | 142 | 1. Operations that don't activate the stream so more operations can come after them in an aggregation \(e.g. `map`, `filter`\). 143 | 2. Operations that activate the stream and doesn't allow more operations to be after them \(e.g. `forEach`\). 144 | 145 | > **Definition 1.2.** _**Intermidiate operations**_ will be located everywhere in the stream expect at the end. They return a stream object and does not execute any operation in the pipeline. 146 | > 147 | > **Definition 1.3.** _**terminal operations**_ will be located only at the end of the stream. They execute the pipeline. They do not return stream object so no other_Intermidiate operations_ or _terminal operations_ can be added after them. 148 | 149 | All the stream methods mention so far: `map`, `filter`, `forEach`- In their execution, they don't need to remember old elements that already calculated. For example,`map` calculate a new value from the value they receive each time. 150 | 151 | A stream will take each element in the source collection and will send him throughout all the operations in the pipeline before dealing with the next element in the source collection. Well, that's a lie, it only behaves like that if all the operations in the pipeline are stateless. In the next chapters, we will investigate stateful operations and when a stateless operation becomes stateful and vise versa. For now, let's view the order of a calculation for each element in the source control in case all the operations in the pipeline are stateless: 152 | 153 | ```java 154 | Arrays.asList(1,2,3).stream() 155 | .filter((Integer x)-> x>1) 156 | .map((Integer x)->x*10) 157 | .forEach(System.out::println); 158 | 159 | source collection: 1, 2 ,3 160 | 161 | filter(1) -> You are not OK. Element 1 will not pass to the next operation 162 | in the pipeline. Now deal with element 2. 163 | filter(2) -> You are OK. element: 2 passes to the next operation. 164 | map(2) -> create new element: 20 and put it in the new stream. 165 | forEach(20) -> print 20. Then, end dealing with the element: 2 in the source collection. 166 | Now deal with the element: 3. 167 | filter(3) -> You are OK. element 3 pass to the next operation 168 | map(3) -> create new element 30 and put it in the new stream. 169 | forEach(20) -> print 30. No more elements in the source collection. 170 | Finish executing the stream. 171 | 172 | output: 173 | 20 174 | 30 175 | ``` 176 | 177 | ![](http://imgur.com/O8pOesF.jpg) 178 | 179 | For examining the order of the operations on elements with a list a single stateful operation, let's review the _sorted_ method: 180 | 181 | | `Stream sorted()` | 182 | | :--- | 183 | | The _**sorted**_ method is an intermediate operation and it will create a new stream that all his elements are sorted according to by natural order. `T` must implement _Comparable_ interface so you can override `int Comparable.compareTo(T o)`. The `sorted` method can't send every element it gets to the next operation in the pipeline because the order of the elements is matters and there is a chance that `sorted` will receive element in the future with smaller value, so this element should be sent first to the next operation in the pipeline. `sorted` use a temporary collection to store all the elements it gets and he starts sorting them from the time it gets executed. | 184 | 185 | ```java 186 | // example: 187 | 188 | Arrays.asList(1,2,3,1,4).stream() 189 | .filter((Integer x)-> x>1) 190 | .sorted() 191 | .forEach(System.out::println); 192 | 193 | // Out put: 194 | // 2 195 | // 3 196 | // 4 197 | ``` 198 | 199 | ![](http://imgur.com/NJI3wlo.jpg) 200 | 201 | Another essential intermediate operation is `limit`. As the name implies, we use it to limit the number of elements we send to the next operation in the pipeline. 202 | 203 | | `Stream limit(long maxSize)` | 204 | | :--- | 205 | | The _**limit**_ method is an intermediate operation that will create a new stream that contains at most `n` elements where `n`=`maxSize`. When `n` elements passed him or the last operation can't give more to `limit`, `limit` will end the execution of the **all** the stream. To answer the question if this operation is stateful or not, we need to understand who are those `n` elements that `limit` let them pass to the next operation in the pipeline. For now, let's think that this operation is stateless and `limit` lets the first `n` elements that he gets to pass at most. | 206 | 207 | ```java 208 | // example 1: 209 | 210 | Arrays.asList(1,2,3,4,5).stream() 211 | .limit(2) 212 | .filter((Integer x)-> x>1) 213 | .forEach(System.out::println); 214 | 215 | // Out put: 216 | // 2 217 | ``` 218 | 219 | ![](http://imgur.com/ciubvZl.jpg) 220 | 221 | ```java 222 | // example 2: (filter and limit swapped) 223 | 224 | Arrays.asList(1,2,3,4,5).stream() 225 | .filter((Integer x)-> x>1) 226 | .limit(2) 227 | .forEach(System.out::println); 228 | 229 | // Out put: 230 | // 2 231 | ``` 232 | 233 | ![](http://imgur.com/oiDX6lN.jpg) 234 | 235 | 236 | As we will see later, we can construct a stream with an infinite amount of elements. In that case, does `sort` will wait forever until the next operation after him in the pipeline will execute? Yes. 237 | 238 | > **Definition 1.4.** Intermediate operations will be called _**short-circuiting operation**_ if that operation produces a new stream with a finite amount of elements from `n` elements where `n` can be an infinite number. 239 | > 240 | > **Definition 1.5.** Terminal operations will be called _**short-circuiting operation**_ if it can finish his execution after a finite amount of time. 241 | 242 | Using `limit` will turn each operation that comes after him in the pipeline into _circuiting operation_. 243 | 244 | The last operation that we will examine in the first chapter is `toArray`. 245 | 246 | | `
A[] toArray(IntFunction generator)` | 247 | | :--- | 248 | | The _**toArray**_ method is a terminal operation that will return a new array of type `A` containing all the elements from the last operation in the pipeline. For now, let's think that `toArray` know exactly how many elements he will receive throughout his execution. `generator` receives Integer `n` and must return `A[]`. The array length is at list equal to `n`. | 249 | 250 | ```java 251 | // example: 252 | 253 | // convert an unsorted list of integers to a sorted array of integers. 254 | Integer[] array=Arrays.asList(3,2,1).stream() 255 | .sorted() 256 | .toArray((int n)->new Integer[n]); 257 | 258 | // the above is equivalent to: 259 | // Integer[] array=Arrays.asList(3,2,1).stream() 260 | // .sorted() 261 | // .toArray(Integer[]::new); 262 | 263 | // print the array 264 | Arrays.stream(array).forEach(System.out::println); 265 | 266 | // output: 267 | // 1 268 | // 2 269 | // 3 270 | ``` 271 | 272 | In the above example, `toArray` operation returned an array of type `Integer` instead of type `int`. That is because `toArray` return array of generic type and Java doesn't allow primitive to function as generic types. Then how can we receive an array of primitive type from the stream? We must build a class or a method that will solve this problem, and that method must know we are interested in the array of a primitive type. 273 | 274 | ### Conclusion 275 | 276 | In this chapter we learned that every stream consists of: 277 | 278 | 1. Data source. 279 | 2. Chain of zero or more intermediate operations. 280 | 3. single terminal operation. 281 | 282 | In the next chapter, we will discover `IntStream` and other streams that deal with primitive types. 283 | -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 2 - Primitive steams.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 2 - Primitive streams 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Types and examples](#chapter-1-types-and-examples) 8 | 9 | ### Introduction 10 | 11 | The interfaces `IntStream`, `DoubleStream`, `LongStream` implement `BaseStream` interface. In addition to `Stream` interface methods, They expose additional methods to query their elements by knowing their type. As you can guess, now we **nicely** calculate the sum, average, min, max of the elements in the stream. 12 | 13 | In this chapter we will examine some of the additional methods from `IntStream` interface is offering compared to `Stream` interface. 14 | 15 | ### Chapter 1: Types and examples 16 | 17 | The first method we will learn is the one who convert`Stream` to `IntStream`. 18 | 19 | | `IntStream mapToInt(ToIntFunction mapper)` | 20 | | :--- | 21 | | Same as `map` operation, this method receive a function `mapper` whos return type is `Integer`. | 22 | 23 | ```java 24 | // example: 25 | 26 | Arrays.asList(3,2,1).stream() 27 | // notice that map get function with Integer parameter because 28 | // the parameter type is generic and the return type must be 29 | // int because we convert the stream to IntStream. 30 | .mapToInt((Integer x)->x) 31 | // notice that map get function with int parameter instead of 32 | // Integer and the return type must be int. 33 | .map((int x)->x*10) 34 | .forEach(System.out::println); 35 | 36 | // the above is equivalent: 37 | // Arrays.asList(3,2,1).stream() 38 | // .mapToInt(Integer::intValue) 39 | // .map((int x)->x*10) 40 | // .forEach(System.out::println); 41 | 42 | // output: 43 | // 30 44 | // 20 45 | // 10 46 | ``` 47 | 48 | | `int sum()` | 49 | | :--- | 50 | | This is a terminal operation which return the sum of all the elements in the stream who called this method. | 51 | 52 | ```java 53 | // example: 54 | 55 | int sum = Arrays.asList(3,2,1).stream() 56 | .mapToInt(Integer::intValue) 57 | .sum(); 58 | 59 | System.out.println(sum); 60 | 61 | // output: 62 | // 6 63 | ``` 64 | 65 | Due to similarities, I will skip `min`,`max` and `summaryStatistics`. 66 | 67 | | ` Stream mapToObj(IntFunction mapper)` | 68 | | :--- | 69 | | This is an intermediate operation. `mapToObj` create from each integer an object from type `U`. This method only purpose is to convert `IntStream` to `Stream`. | 70 | 71 | ```java 72 | // example: 73 | 74 | Arrays.asList(1,2,3).stream() 75 | // convert Stream to IntStream. 76 | .mapToInt(Integer::intValue) 77 | // invoke some intermediate operations on IntStream. 78 | // ... 79 | // ... 80 | // ... 81 | // convert IntStream to Stream. 82 | .mapToObj((int x)-> "element value is: "+x) 83 | .forEach(System.out::println); 84 | 85 | // output: 86 | // element value is: 1 87 | // element value is: 2 88 | // element value is: 3 89 | ``` 90 | 91 | Incase we want to convert `IntStream` to `Stream` we can use `boxed`: 92 | 93 | | `Stream boxed()` | 94 | | :--- | 95 | | This is an intermediate operation. Same as `mapToObj` its main diffrence is the return type is completely known. It is a special case of `mapToObj`. | 96 | 97 | ```java 98 | // example: 99 | 100 | Arrays.asList(1,2,3).stream() 101 | // convert Stream to IntStream. 102 | .mapToInt(Integer::intValue) 103 | // convert IntStream to Stream. 104 | .boxed() 105 | .forEach(System.out::println); 106 | 107 | // output: 108 | // 1 109 | // 2 110 | // 3 111 | ``` -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 3 - Optional class.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 3 - Optional class 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Operations](#chapter-1-operations) 8 | 3. [Conclusion](#conclusion) 9 | 10 | ### Introduction 11 | 12 | 13 | Some terminal operations return an object that is made or equal from/to one or more elements in the stream. What happens when the source collection is empty, or none of the elements in the source collection survived all the pipeline until coming to the terminal operation? 14 | 15 | Returning `null` is an option but a bad one. The following reasons may cause `NullPointerExcaption`: 16 | 17 | 1. We forgot to initialize an object. 18 | 2. We received a `null` pointer from a function and we did not check it. 19 | 20 | Let's focus on the second reason - Do we know if the null we received is a bug of the programmer who wrote the function or the function should return us `null` for that call? 21 | 22 | To avoid some of the reasons for `NullPointerExcaption`, Java 8 introduced us the `Optional` type. It comes with intermediate and terminal operations to deal with the absence/ presence of a value. 23 | 24 | Note: While the _intermediate operations_ of streams run when there is a call to a terminal operation, the optional's _intermediate operations_ executed immediately. 25 | 26 | ### Chapter 1: Operations 27 | 28 | We will examine the basic operations of `Optional` and then see some stream's terminal operations that return an `Optional`: 29 | 30 | 31 | | `public boolean isPresent()` | 32 | | :--| 33 | | The _**isPresent**_ terminal operation returns true if it represents an existing value, else returns false. | 34 | 35 | | `public void ifPresent(Consumer consumer)` | 36 | | :--| 37 | | If the object who call this method represents an existing value, the _**isPresent**_ terminal operation will invoke `consumer` function on the existing value. Else do nothing. | 38 | 39 | | `public static Optional ofNullable(T value)' | 40 | | :--| 41 | | The _**ofNullable**_ function will return an optional representing a value. Use it **only** when you aren't sure if `value` is equal to `null`. If `value` is equal to `null`, this function will return an empty `optional` object (invoking `isPresent` terminal operation on an empty optional object return `false` and an empty `optional` object is not guaranteed to be a singleton.) | 42 | 43 | | `public static Optional of(T value)' | 44 | | :--| 45 | | The _**of**_ function will return an optional representing a non-null value. Use it **only** when you are sure that `value` is not equal to `null`. A `NullPointerExcaption` will be thrown in case `value` is equal to `null`. | 46 | 47 | ``` java 48 | // example: 49 | 50 | Optional.of(123) 51 | .ifPresent((Integer existingValue)-> System.out.println(existingValue)); 52 | 53 | // the above is equivalent to: 54 | // Optional.of(123) 55 | // .ifPresent(System.out::println); 56 | 57 | // output: 58 | // 123 59 | ``` 60 | 61 | | `public Optional map(Function mapper)` | 62 | | :-- | 63 | | If the object who call this method represents an existing value, the _**map**_ intermediate operation will invoke `mapper` on the existing value. `map` return type is an `Optional`. When the value is absent, return an empty `Optional`. `U` is the return type of `mapper`. | 64 | 65 | | `public Optional filter(Predicate predicate)` | 66 | | :-- | 67 | | If the object who call this method represent a existing value and `predicate` return `true` then return an `Optional` with the same value. Else return an empty `Optional`. | 68 | 69 | ```java 70 | // example 1: 71 | 72 | Optional.of(1) 73 | .filter((Integer existingValue) -> existingValue > 0) 74 | .map((Integer existingValue) -> "optional value is: " + existingValue) 75 | .ifPresent(System.out::println); 76 | 77 | // output: 78 | // optional value is: 123 79 | 80 | ``` 81 | 82 | ``` java 83 | // example 2: 84 | 85 | Optional.of(1) 86 | .filter((Integer existingValue) -> existingValue > 1) 87 | .map((Integer existingValue) -> "optional value is: " + existingValue) 88 | .ifPresent(System.out::println); 89 | 90 | // output: 91 | // (no output) 92 | ``` 93 | 94 | After examining the basic functions of `Optional`let's go back to streams and look at a terminal operation who return `Optional` object: 95 | 96 | | `Optional findAny()` | 97 | | :--| 98 | | The _**findAny**_ method is a terminal operation that will return one element from the caller stream. It may return a different element for each execution. Later we will see why this behavior is better for performance. In case the caller stream is empty for any reason, return an empty `Optional` object. | 99 | 100 | ```java 101 | // example: 102 | 103 | Arrays.asList(14,13,12,11,10) 104 | .stream() 105 | .sorted() 106 | .findAny() 107 | .map((Integer element)-> element*element) 108 | .ifPresent(System.out::println); 109 | 110 | //possible output: 111 | // 100 112 | ``` 113 | 114 | We will cover much more powerful terminal operation which returns `Optional` object in the next chapter. 115 | 116 | --- 117 | 118 | ### Conclusion 119 | 120 | The `Optional` type help us to replace the old `if(value==null)` statement by building a pipeline to deal with the absence/presence of a given value. There are more operations we didn't cover. Go to [Optional class methods](#optional-class-methods) chapter to read more about `Optional` operations. -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 4 - Reduction.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 4 - Reduction 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Reduction types](#chapter-1-reduction-types) 8 | 2. [Java reduction](#chapter-2-java-reduction) 9 | 4. [Conclusion](#conclusion) 10 | 11 | ### Introduction 12 | 13 | `Reduce` in the context of functional programming is an operation to calculate a single value from a given collection. The reduce operation calculate it results from each element in the collection. The way he does that is by saving a temporary result and calculating a new temporary result from the last temporary result and an element he did not visit yet. The function who calculate the next temporary result is called `accumulator`. We must supply it to the reduce operation. 14 | 15 | For example: 16 | If we want to sum all the elements in a given array: `{10`,`11`,`12}` , reduce operation determine the first temporary result to be '10' and the accumulator function to be: `(Integer lastResult, Integer element) -> lastResult + element`. 17 | In the first iteration, `10` which is the first temporary result and `11` which is an unvisited element will be sending to our accumulator for calculating the next temporary result: `21`. 18 | In the second and last iteration, `21` and `12` will be sending to our accumulator for calculating the final result: `33`. 19 | 20 | Notes: 21 | 22 | 1. The accumulator operation does not mutate any temporary result or any element in the collection. It creates new temporary result in each iteration. 23 | 2. The accumulator operation must be associative; For any three values `x`, `y` and `z`, the evaluation of `accumulator.apply(accumulator.apply(x,y),z)` equals to `accumulator.apply(x,accumulator.apply(y,z))`. Examples for non-associative accumulators: `%`, `/`: `2/(2/2)` isn't equal to (`2/2)/2`. In parallel execution (which we will examine in depth soon), the reducer operation will take advantage of this rule by expanding it recursively to four values. 24 | 3. The reduce operation can run in parallel, but more information on parallel will come later. 25 | 26 | ### Chapter 1: Reduction types 27 | 28 | There are 2 types of Reduce operations: 29 | 30 | > **Definition 5.1.** **_Reduce-left_** operation determine the first temporary result will be the first element in the collection from the left and the reduce operation will visit each element in the collection that he didn't visit yet from left to right. 31 | 32 | The example we have seen above is a reduce-left operation. 33 | 34 | > **Definition 5.2.** **_Reduce-right_** operation determine the first temporary result will be the first element in the collection from the right, and the reduce operation will visit each element in the collection that he didn't visit yet from right to left. 35 | 36 | ### Chapter 2: Java reduction 37 | 38 | Java implements _reduce-left_ operation: 39 | 40 | |`Optional reduce(BinaryOperator accumulator)`| 41 | |:--| 42 | | The **_reduce_** operation calculates the result from each element in the collection using an accumulator. It is a _reduce-left_ operation, so the first element from the left is the initial temporary result. This method return `Optional` because the calling stream may be empty. | 43 | 44 | ```java 45 | // example: finding sum 46 | 47 | Arrays.asList(2,3,4,5,6) 48 | .stream() 49 | .reduce((resultUntilNow,element)-> resultUntilNow + element) 50 | .ifPresent(System.out::println); 51 | 52 | // output: 53 | // 20 54 | ``` 55 | ![](http://i.imgur.com/srRPrc3.jpg) 56 | 57 | Reduce works in parallel by splitting the work to be done in smaller portions. 58 | Each thread takes a smaller task and calculating a temporary result using the accumulator and determining an initial temporary result for each portion of the collection. After finishing each task, the provided accumulator combine partial results into one. We can see that the reduction can run in parallel only with a given accumulator and without any additional synchronization. 59 | 60 | The following image presents parallel computing of the reduce operation when the reduce split the work to 2 threads (can be more). 61 | 62 | ![](http://i.imgur.com/DkU20og.jpg) 63 | 64 | As mentioned earlier, due to the fact that there are more then 3 elements in the collection, the reduce operation take advantage of the associativity because all the following forms of computations are **equal**: 65 | 66 | 1. `accumulator.apply(accumulator.apply(accumulator.apply(x,y),w),z)` 67 | 2. `accumulator.apply(accumulator.apply(x,y),accumulator.apply(w,z))` 68 | 69 | _Note:_ The transformation from the first form to the second is immediate (without any intermediate steps) by the definition of associativity and the fact that `accumulator.apply` is associative. 70 | 71 | As we can see, in the second form, we can calculate `accumulator.apply(x,y)` and `accumulator.apply(w,z)` in parallel and combine the results later using `accumulator.apply`. 72 | 73 | Also, As a challenge, I leave to the reader the task to activate the associativity rule on array of `5` elements so the reduce operation will support parallel invocations of `accumulator.apply` as much as possible. 74 | 75 | ---- 76 | The next overloading of the `reduce` operation in Java also receive an _identity_. 77 | 78 | Instead of letting reduce operation determine the first left value to be the initial temporary result, we can declare it, and this value is called the _identity_ value. 79 | 80 | This type of reduction is called `folding`. Java uses fold-left reduction by default. 81 | 82 | | `T reduce(T identity, BinaryOperator accumulator)` | 83 | | :--- | 84 | | In a synchronized execution, the **_reduce_** operation use the _identity_ value only once as an initial temporary result. The calculating is the same as the first overload we saw. In case of parallel running, it will work as described above. In case the calling stream doesn't have any elements, the `reduce` method returns the _identity_ value as a result. | 85 | 86 | ``` java 87 | // example: finding max. 88 | 89 | Integer result = Arrays.asList(2,3,4,5,6) 90 | .stream() 91 | .reduce(Integer.MIN_VALUE, (Integer resultUntilNow, Integer element)-> 92 | Math.max(resultUntilNow,element)); 93 | System.out.println(result); 94 | 95 | // output: 96 | // 6 97 | ``` 98 | ![](http://i.imgur.com/2CUx0Cd.jpg) 99 | 100 | The third and last overloading of `reduce` operation in Java also receives a _combiner_. 101 | 102 | After each thread finished his task, instead of using the provided accumulator function to combine the partial results, we can provide a _combiner_ function for that. The logic of the combiner can be different from the accumulator. 103 | In case the run is sequential, there will be no use in the provided combiner function. 104 | 105 | | ` U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)` | 106 | | :--- | 107 | | In a synchronized execution running, the _**reduce**_ operation use the _identity_ value only once as an initial temporary result. The _identity_ type can be different from the elements in the calling stream. The calculating is the same as the first overload we saw. In case of parallel running, it will work as described above. In case the calling stream as no elements, return the _identity_ value as a result. | 108 | 109 | ```java 110 | // example: joining all elements 111 | 112 | String result = Arrays.asList(2,3,4,5,6) 113 | .stream() 114 | .reduce("", (String resultUntilNow, Integer element)-> resultUntilNow+element, 115 | (String partialResult1,String partialResult2)->partialResult1.concat(partialResult2)); 116 | 117 | System.out.println(result); 118 | 119 | // output: 120 | // 23456 121 | ``` 122 | 123 | --- 124 | 125 | ### Conclusion 126 | 127 | The reduce operation does not mutate it's state and create new one state in each iteration. In the last example, we saw that the reduce copy multiple strings multiple times. The complexity of that is too high. In the next chapter, we will see an alternative approach to this problem, but it will cost us something else. 128 | 129 | All in all, we have seen that for each reduction we must provide an accumulator function and an optional identity or combiner function. Both the accumulator and the combiner must be stateless and pure functions to support parallel execution. -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 5 - Collectors.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 5 - Collectors 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Reduce vs Collector](#chapter-1-reduce-vs-collector) 8 | 3. [toList() collector](#chapter-2-tolist-collector) 9 | 4. [Simple toList() collector implementation](#chapter-3-simple-tolist-collector-implementation) 10 | 5. [Collectors in the standard library](#chapter-4-collectors-in-the-standard-library) 11 | 4. [Conclusion](#conclusion) 12 | 13 | ### Introduction 14 | 15 | The reduce operation we have seen above is powerful but come with a price - runtime complexity. Sometimes we prefer to mutate a state to receive a better complexity. 16 | 17 | Java 8 created for us classes which implement the `Collector` interface. The concept of a collector and a reduce operation is similar - both operations calculate a value from multiple values. 18 | 19 | | Collector Interface - Abstract Methods| 20 | | :--- | 21 | | `BiConsumer accumulator()` | 22 | | `BinaryOperator combiner()` | 23 | | `Supplier supplier()` | 24 | | `Function finisher()` | 25 | | `Set characteristics()` | 26 | 27 | `T` - The input elements type of the calling stream. 28 | `A` - The return type of the mutable accumulation operation. 29 | `R` - The result type of the finisher operation. 30 | 31 | The accumulator and the combiner are familiar to us from the reduce operation. The supplier is replacing the `identity` value we provided, meaning we can manage the creation logic of the `identity` value to each thread inside the scope of the collector. 32 | The finisher is a function that can change the final result of the collector. The last method is the `characteristics` who return a `Set` of flags. Each flag indicates a specific behavior the collector support. All the flags are used by the `Stream.collect` 'terminal operation who run the collector, to gain better performance. We will discuss flags later. 33 | 34 | ### Chapter 1: Reduce vs Collector 35 | 36 | The main differences between the `reduce` operation and a collector are: 37 | 38 | 1. Reduce operation forbid mutating any variable inside the accumulator function. Instead of mutating the temporary result, it creates and returns a new temporary result. On the other hand, collectors do not behave the same. We will see that instead of returning a new temporary result in each iteration, it will mutate it each time in the accumulator function so this accumulator does not return anything. Nevertheless, the collector still supports parallel execution. 39 | 40 | 2. Instead of supply an `identity` value to the reduce, we can provide a lambda (`supplier`) to the collector, so the logic of the `identity` value creation stays inside the collector scope only. 41 | 42 | 3. The reduce operation doesn't support changing its final result inside its scope, but the collector supports this kind of behavior. 43 | 44 | 4. Pre-defined flags can tell the stream operation which runs the collector how to execute. The following flags can be used: 45 | 46 | | `Collector.Characteristics enum`| 47 | | :--- | 48 | | `CONCURRENT` - We can access the resulting container (collection or an object) from the accumulator function concurrently. In this case, the supplier should be called only once. | 49 | | `IDENTITY_FINISH` - We doesn't change the resulting container, and the finisher function is: `(A container) -> container` | 50 | | `UNORDERED` - The resulting container doesn't keep his elements in any order. Another way to think about that is, you can't use `for` loop to print the container elements. For example `HashMap`. This flag is meant to tell the operation `Stream.collect` that we do not care in what order the elements will be inserted into the final container. For example, if the flag `CONCURRENT` is off, that means we must split the work into smaller temporary containers. Meaning each thread will do a smaller task and will insert the elements in the different container. Because the container doesn't care about what order we insert elements, we don't need to wait for thread `n` to copy his result to a bigger container before thread `n-1` did that. We let any thread who finish his task to copy his result to a bigger container.| 51 | 52 | ### Chapter 2: toList() collector 53 | 54 | Java 8 wrote for us some collectors we can use for free inside the `Collectors` class. We can use them by calling `Stream.collect` that accept a `Collector`. 55 | The collect terminal operation will use the accumulator, supplier, combined, finisher and the characteristics function from the collector object to run. 56 | 57 | 58 | | `public static Collector> toList()` | 59 | | :--- | 60 | | The __*toList*__ collector converts the calling stream to a `List`. There is no guarantee to which class will be used to create the list. Also no guarantee on the thread-safety or the serializability of that class. | 61 | 62 | ``` java 63 | // example: 64 | 65 | List list1= Arrays.asList(2,3,4,5) 66 | .stream() 67 | .filter((Integer x)-> x >= 3) 68 | // Collectors.toList() return a collector object! 69 | .collect(Collectors.toList()); 70 | list1.forEach(System.out::println); 71 | 72 | // output: 73 | // 3 74 | // 4 75 | // 5 76 | ``` 77 | 78 | ### Chapter 3: Simple toList() collector implementation 79 | 80 | Lets have a look at a possible implementation of the `toList` collector: 81 | 82 | ``` java 83 | class MyToListCollector implements Collector,List> // Collector 84 | { 85 | // T = T - The input elements type of the calling stream. 86 | // A = List - The return type of the mutable accumulation operation. 87 | // R = List - The result type of the finisher operation. 88 | 89 | @Override 90 | public Supplier> supplier() { 91 | return ()-> new LinkedList(); 92 | } 93 | 94 | @Override 95 | public BiConsumer, T> accumulator() { 96 | return (List temporaryContainer,T element)-> temporaryContainer.add(element); 97 | } 98 | 99 | @Override 100 | public BinaryOperator> combiner() { 101 | return (List temporaryContainer1,List temporaryContainer2)-> { 102 | // if we report the Collector.Characteristics.CONCURRENT flag, 103 | // it means the container we are using to store the elements, 104 | // can be used for adding elements concurrently. 105 | // In this case, all the threads will use the same container and this 106 | // function, combiner, won't be called. 107 | // if we doesn't report the Collector.Characteristics.CONCURRENT flag, 108 | // it means the container we are using to store the elements, 109 | // can't be used for adding elements concurrently. In this case each 110 | // thread run the supplier function to create his temporary container 111 | // and when he is done adding his elements, he need to combine his 112 | // temporary container with other temporary containers. 113 | // In this case this function, combiner, will be called at list once. 114 | // Inside the combiner, we doesn't need to create new temporaryContainer 115 | // to hold both the given temporary containers because no other thread is 116 | // currently using temporaryContainer1 or temporaryContainer2. 117 | // Again, we didn't report the Collector.Characteristics.CONCURRENT flag 118 | // so 2 or more threads can't add to the same container. 119 | temporaryContainer2.forEach((T element)-> temporaryContainer1.add(element)); 120 | return temporaryContainer1; 121 | }; 122 | } 123 | 124 | @Override 125 | public Function, List> finisher() { 126 | return Function.identity(); // Function.identity() return: (List container) -> container; 127 | } 128 | 129 | @Override 130 | public Set characteristics() { 131 | Set characteristics=new HashSet(); 132 | // For this implementation I choosed, I didn't change the final container 133 | // in the finisher function so it doesn't need to be called. 134 | characteristics.add(Characteristics.IDENTITY_FINISH); 135 | return characteristics; 136 | } 137 | } 138 | ``` 139 | 140 | ### Chapter 4: Collectors in the standard library 141 | 142 | More collectors Java 8 provide us inside the `Collectors` class are: 143 | 144 | | `public static Collector>> partitioningBy(Predicate predicate)` | 145 | | :--- | 146 | | This collector partition the incoming elements into 2 groups: The elements which `predicate` return true for them and the second group is the rest. The result container implements `Map`.| 147 | 148 | ```java 149 | // example: 150 | 151 | Map> result= Arrays.asList(2,3,4,5) 152 | .stream() 153 | .collect(Collectors.partitioningBy(number-> number % 2 == 0)); 154 | 155 | result.entrySet().forEach(group -> System.out.println(group.getValue().size())); 156 | 157 | // output: 158 | // 2 159 | // 2 160 | ``` 161 | 162 | | `public static Collector>> groupingBy(Function classifier)` | 163 | | :--- | 164 | | This collector creates a `Map`. Each element is sent to the `classifier` function that generates a key. The value for each key is a collection of all the elements which produce the same key. The collection stored in each value implements `List`. If you want to choose which collection to use, choose a different overload. API Note: In parallel running, each accumulator adds elements to different `Map` object and the combiner is merging them. You should use a different function to have better performance: `groupingByConcurrent` | 165 | 166 | ```java 167 | // example: 168 | 169 | Map> result= Arrays.asList(1,2,3,4,5,6,7,8) 170 | .stream() 171 | // the keys can be 0 or 1 or 2 or 3 only. 172 | .collect(Collectors.groupingBy( x -> x%4)); 173 | 174 | result.entrySet().forEach(keyAndValue-> 175 | System.out.println("Key: " + keyAndValue.getKey() + 176 | " , amount of elements:" + keyAndValue.getValue().size())); 177 | 178 | // output: 179 | // Key: 0 , amount of elements:2 180 | // Key: 1 , amount of elements:2 181 | // Key: 2 , amount of elements:2 182 | // Key: 3 , amount of elements:2 183 | ``` 184 | Some collectors who return `Map` Accept collector as an argument. That is for transforming the elements inside each value to something else. They can transform the elements inside the value into an Integer that represent the amount of all the element who are inside the value or doing something else with those elements. Let's have a look at the overload and some examples: 185 | 186 | | `public static Collector> groupingBy(Function classifier, Collector downstream)` | 187 | | :--- | 188 | |This overload has the same behavior as the last overload including some API notes. The difference here is that each element that produces the same key will be sent to the `downstream` collector. Each key will create different `downstream` collector. It means that if we have `n` keys and each key have `m` elements that produce that key, there will be `n` different `downstream` collectors for each `m` elements.| 189 | 190 | ```java 191 | // example 1: 192 | 193 | Map result= Arrays.asList(1,2,3,4,5,6,7,8) 194 | .stream() 195 | .collect(Collectors.groupingBy((Integer x) -> x%4, 196 | // Collectors.counting() is a collector that return 197 | // the number of incoming elements. 198 | Collectors.counting())); 199 | 200 | result.entrySet().forEach(keyAndValue-> 201 | System.out.println("Key: " + keyAndValue.getKey() + 202 | " , amount of elements:" + keyAndValue.getValue())); 203 | // output: 204 | // Key: 0 , amount of elements:2 205 | // Key: 1 , amount of elements:2 206 | // Key: 2 , amount of elements:2 207 | // Key: 3 , amount of elements:2 208 | ``` 209 | 210 | The possibility of running the second collector inside a collector is very powerful. 211 | 212 | ```java 213 | // example 2: 214 | 215 | Map>> result= Arrays 216 | .asList(0,1,10,11,100,101,1000,1001,1002,1003) 217 | .stream() 218 | .collect(Collectors.groupingBy( 219 | (Integer x) ->x.toString().length() , 220 | Collectors.groupingBy((Integer x) -> x%2 == 0))); 221 | 222 | // Describing the result object will be less scary 223 | // then showing what there is inside: 224 | // the length of the numbers are the keys. 225 | // meaning we have 4 different keys in this value: 226 | // 1 (0,1), 2 (10,11), 3 (100,101), 4 (1000,1002,1001,1003). 227 | // Instead of collecting each key's values in a List, 228 | // I used a second group by to seperate them by even and odds. 229 | // meaning the keys will be : true (even) and false (odd). 230 | // All in all result looks like this: // is 231 | // an element in a map 232 | // key: 1 , value: , 233 | // key: 2 , value: , 234 | // key: 3 , value: , 235 | // key: 4 , value: , 236 | ``` 237 | --- 238 | ### Conclusion 239 | 240 | You will notice that there is a `reducing` collector. This operation can have `identity` value, `accumulator` and a `combiner` (Same as `Stream.reduce`). Why Java 8 created 2 reducers who operate the same? The answer is to let us use reduction inside _multi-level_ collectors. For example, we can use `reducing` collector inside a `groupingBy` collector. The research about _multi-level_ collectors is left to the reader. -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 6 - Spliterator.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 6 - Spliterator 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [The spliterator interface](chapter-1-the-spliterator-interface) 8 | 3. [Spliterator methods](chapter-2-the-spliterator-methods) 9 | 4. [Spliterator in Java streams](chapter-3-spliterator-in-java-streams) 10 | 11 | ### Introduction 12 | 13 | In the following paragraphs, let's stop thinking about streams and return the good old collections and how to iterate them. You probably heard or used `Iterators`. they are great but not suitable for all the problems we are facing today. One of those is parallel calculating. 14 | 15 | As we saw earlier, we can split the calculation on an array to calculate smaller chunks of the same array in parallel and after that, combining the temporary results to one final result. Splitting a collection can be done in different types of collections and not only arrays. Which types of a collection can we split? The ones we know their estimated `SIZE`. After splitting a binary tree, does the sub-trees are also splittable; Do we know their estimated `SIZE`? The answer is yes only for balanced trees. If we do know their `SIZE` after the splitting, we can say that the `SIZE` of the collection is known and also the sub-trees; The collection is also `SUBSIZED`. 16 | 17 | 18 | ### Chapter 1: The spliterator interface 19 | 20 | A `Spliterator` is a new interface in Java 8. Each collection in Java implements and return a spliterator same as returning an iterator. Both can be used to iterate over a given collection, but spliterator can also be used to split the work to smaller tasks for parallel computing. A spliterator can also represent a generator function or an IO channel. If we choose to split the collection which the spliterator is iterating over and succeed(we soon examine the reasons for failed), the spliterator will now be responsible to only half+-(we will explain later why not precisely half) the elements he should have iterate before the splitting and the new spliterator that will be created after the splitting will iterate on the rest of the elements; The other half. We can keep splitting the spliterator work recursively until there is nothing to split or we don't know the estimated `SIZE` of the spliterator (those are the reasons for failer of the splitting operation). 21 | 22 | `SIZE` and `SUBSIZED` are only 2 characteristics a spliterator can have. We have 5 more: 23 | 24 | | Characteristic| | 25 | | :-------------| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 26 | | `CONCURRENT` | It's possible to modify (delete/insert/replace elements) the source of the spliterator concurrently without any additional synchronization. 27 | | `NONNULL` | The source of the spliterator can't insert null elements, so each of the elements is guaranteed to be a non-null value. | 28 | | `IMMUTABLE` | The source of the spliterator prohibit modification (delete/insert/replace elements). | 29 | | `DISTINCT` | For each 2 different elements `x` and `y` in the source of the spliterator we can tell that `x.equals(y) == false`. | 30 | | `ORDERED` | If we print the elements in the source of the spliterator multiple times by iterating it, we will print the elements in the same order time after time. That means all the elements are stored in the source of the spliterator in a specific order. We can refer to that situation by specifying that the source of the spliterator has _encounting order_. For example: `Array`, `List`,`Stuck` has _encounting order_ but `HashMap` doesn't. We can't iterate over `HashMap`. | 31 | | `SORTED` | The source of the spliterator is ordered by a comparator or in the _natural order_. | 32 | | `SIZED` | We know the estimated amount of iterations left in the spliterator. | 33 | | `SUBSIZED` | If we split the task into 2 chunks, we would know the estimated amount of iterations each spliterator would have. Note: If `SUBSIZED` is on, then `SIZED` also. The reason is if we know how many iterations will be needed after the split for each spliterator, we must know first how many iterations left without splitting in the first place. The claim doesn't follow for the opposite direction as mentioned above. For example - binary trees. | 34 | 35 | ### Chapter 2: Spliterator methods 36 | 37 | Let's examine the basic abstract methods of `Spliterator` interface: 38 | 39 | | `boolean tryAdvance(Consumer action)` | 40 | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 41 | | If the spliterator did not iterate over all the elements yet, return `true` and perform `action` on the next element in the source of the spliterator. Then advance the spliterator to point to the next element. If there are no elements to iterate over, return false and don't invoke `action` because there is no element to send to the action anyway. If we used `Iterator` instead of `Spliterator`, then we must have called two methods instead of one: `hasNext` and `next`. Now the interface is cleaner and less imperative. __Notes:__ __1.__ If `ORDERED` characteristic is off, then there is no guarantee which element will be visited by the spliterator using this method from the remaining elements. __2.__ After the split, each spliterator on the source collection will iterate over fewer elements now than using a single iterator. That means this method is checking how many elements this spliterator have left before finish his sub-task. 42 | 43 | ```java 44 | // example: 45 | 46 | boolean didWeIterate = Arrays.asList(1,2,3) 47 | .spliterator() 48 | .tryAdvance((Integer x)-> System.out.println(x)); 49 | 50 | System.out.println(didWeIterate); 51 | 52 | // output: 53 | // 1 54 | // true 55 | ``` 56 | 57 | | `long estimateSize()` | 58 | | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 59 | | If the `SIZED` characteristic is on and we did not iterate the source yet, return the exact number of elements left to iterate over. Else try to compute an estimated number of iterations left. If it is too expensive to compute or unknown or infinite, then return `Integer.MAX_VALUE`.| 60 | 61 | | `Spliterator trySplit()` | 62 | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 63 | | Even if the `SUBSIZED` or `SIZED` characteristics is off, this method will try to split the remaining iterations to 2 different spliterators. If it failed to do so or the spiterator that this method is invoked by was iterating before calling this method or data structure constraints/ efficiency considerations, the method will return null. __Note:__ An ideal splitting will divide the elements exactly in half for parallel computing. For example, in a balanced binary tree, there should be no problem to do so. | 64 | 65 | ```java 66 | // example: 67 | 68 | public static void main(String[] args) { 69 | Spliterator spliterator = Arrays.asList(1,2,3,4).spliterator(); 70 | splitTheWork(spliterator); 71 | 72 | // output: 73 | // 1 74 | // 2 75 | // 3 76 | // 4 77 | } 78 | 79 | static void splitTheWork(Spliterator spliterator1) { 80 | 81 | // spliterator2 will get the first half and spliterator1 will get the second half 82 | Spliterator spliterator2=spliterator1.trySplit(); 83 | if(spliterator2==null) { 84 | while (spliterator1.tryAdvance(System.out::println) == true); 85 | 86 | // the above line is equal to: 87 | // spliterator1.forEachRemaining(System.out::println); 88 | // For more information, see Spliterator interface methods chapter. 89 | } 90 | else { 91 | splitTheWork(spliterator2); 92 | splitTheWork(spliterator1); 93 | } 94 | } 95 | ``` 96 | 97 | --- 98 | 99 | ### Chapter 3: Spliterator in Java streams 100 | 101 | Streams iterate over the source collection using spliterators. When iterating over a stream in parallel, we will use `trySplit` to split the work, but the method may return null due to the reasons we mentioned earlier and the rest (or all) the calculation will be performed sequentially. 102 | 103 | When we transform the source collection to a stream, the stream uses the spliterator, returned from that collection, to iterate over the elements and each _intermediate operation_ will return a new stream that uses the same spliterator. 104 | 105 | Stream uses an internal enum to manage the relevant characteristics for him, `StreamOpFlag`. Each pipeline has its flags. The flags at the beginning are initialized to be the relevant characteristics from the spliterator. A _intermediate operation_ and _terminal operation_ can modify the spliterator characteristics or the _flags_ of the whole pipeline or examine the spliterator's characteristics for choosing the best algorithm. 106 | For example, the `filter` _intermediate operation_ can reduce the number of elements which sent to him. The stream library can not guess how many elements left so if the `SIZED` flag and characteristic is on, now they are off. 107 | 108 | The following table showes which operations types are allowed to modify charactersiticts: 109 | 110 | | | `DISTICTS` | `SORTED` | `ORDERED` | `SIZED` | `SHORT_CIRCUIT` | 111 | | :-------------------------- | :-----------: | :---------: | :-------------: | :------------: | :---------------:| 112 | | __Source stream__ | `Y` | `Y` | `Y` | `Y` | `N` | 113 | | __Intermediate operation__ | `PCI` | `PCI` | `PCI` | `PC` | `PI` | 114 | | __Terminal operation__ | `N` | `N` | `PC` | `N` | `PI` | 115 | 116 | * `Y` - Allowed to have 117 | * `P` - May preserves 118 | * `C` - May clears. 119 | * `I` - May injects. 120 | * `N` - Not valid; Irelevant for the operation. 121 | 122 | __Notes:__ 123 | 1. `SHORT_CIRCUIT` means an operation is considered to be _short circuit operation_ (Explained in chapter 1). 124 | 2. For now, we can see that the Java stream library doesn't use `CONCURRENT`,`NONNULL`, `IMMUTABLE`. That doesn't mean they won't use them in the future. If `SIZED` is off, then `SUBSIZED` will be too. For now, there is no operation which clears or injects the `SUBSIZED` characteristic. 125 | 3. The existence of `SHORT_CIRCUIT` flag implies that the above flags are not from the `Spliterator` Interface characteristics but from `StreamOpFlag` enum that uses the relevant flags he needs for streams optimizations. 126 | 127 | The following table shows which characteristics and flags each _intermediate operation_ may turn on and off: (`SHORT_CIRCUIT` is relevant only in the context of `StreamOpFlag` flags) 128 | 129 | | | DISTINCT | SORTED | ORDERED | SIZED | SHORT_CIRCUIT | 130 | | ---------------- | ----------| --------| ---------| -------| ---------------| 131 | | `filter` | | | | `C` | | 132 | | `forEach` | | | `C` | | | 133 | | `forEachOrdered` | | | | | | 134 | | `allMatch` | | | `C` | | `I` | 135 | | `distinct` | `I` | | | `C` | | 136 | | `flatMap` | `C` | `C` | | `C` | | 137 | | `anyMatch` | | | `C` | | `I` | 138 | | `collect` | | | | | | 139 | | `unOrdered` | | | `C` | | | 140 | | `count` | `C` | `C` | `C` | `C` | | 141 | | `findAny` | | | `C` | | `I` | 142 | | `findFirst` | | | | | `I` | 143 | | `flatMapToXXX` | `C` | `C` | | `C` | | 144 | | `limit` | | | | `C` | `I` | 145 | | `map` | `C` | `C` | | | | 146 | | `mapToXXX` | `C` | `C` | | | | 147 | | `max` | | | | | | 148 | | `min` | | | | | | 149 | | `noneMatch` | | | `C` | | `I` | 150 | | `peek` | | | | | | 151 | | `reduce` | | | | | | 152 | | `skip` | | | `C` | `I` | | 153 | | `sorted` | | `I` | `I` | | | 154 | | `toArray` | | | | | | 155 | 156 | ```java 157 | // example: 158 | 159 | Arrays.asList(1,2,3,4,5,6) // ORDERED SIZED SUBSIZED 160 | .stream() // no change -> ORDERED SIZED SUBSIZED 161 | .distinct() // ORDERED DISTINCT 162 | .filter((Integer element) -> element > 4) // ORDERED DISTINCT 163 | .sorted() // ORDERED DISTINCT SORTED 164 | .forEach(System.out::println); // no change -> ORDERED DISTINCT SORTED 165 | ``` -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Part 7 - Parallel Streams.md: -------------------------------------------------------------------------------- 1 | # Java streams - Part 7 - Parallel Streams 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | ### Topics 5 | 6 | 1. [Introduction](#introduction) 7 | 2. [Example for parallel Java stream](#chapter-1-example-for-parallel-java-stream) 8 | 3. [Concurrent vs parallel programming](#chapter-2-concurrent-vs-parallel-programming) 9 | 4. [Fork/Join framework introduction](#chapter-3-forkjoin-framework-introduction) 10 | 5. [Conclusion](#conclusion) 11 | 12 | --- 13 | 14 | ### Introduction 15 | 16 | Streams can split the source collection to multiple threads by letting each thread work on the different area in the source collection. We use the intermediate operation `Stream.parallel` to get a stream that will __try to__ be a parallel stream. Each stream operation will examine the stream flags and the spliterator characteristics to see if parallel execution is worth. If intermediate operation `A` agreed to execute in parallel, all the stateless intermediate operations after `A` would do too until we meet a stateful operation `B` that has its own rules. 17 | 18 | --- 19 | 20 | ### Chapter 1: Example for parallel Java stream 21 | 22 | ```java 23 | int sum = Arrays.asList(1,2,3,4,5,6,7,8) // ORDERED SIZED SUBSIZED 24 | // every collection have .stream() and 25 | //.parallelStream() methods. 26 | .parallelStream() 27 | // stream know the source collection size and 28 | // how to split it equeal so filter may run 29 | // in parallel if the amount of elements is not 30 | // too small. 31 | .filter(x -> x > 0) // ORDERED 32 | // 1. because the ORDER characteristic is still 33 | // on, limit will return the first 3 elements 34 | // from the source collection that survived until 35 | // limit operation. It may be that there 36 | // are N threads involved in this execution. 37 | // In case the first thread contain the first 3 38 | // elements, then even if the N-1 threads 39 | // got in here, they will not pass the limit 40 | // because limit is still waiting for the first 3 41 | // elements from the first thread. 42 | // As a result, all the threads are stuck here. 43 | .limit(3) // SIZED ORDERED 44 | // stream know how many elements are at this moment 45 | // so filter may run in parallel. if the amount of 46 | // elements is too small, he will choose not to. 47 | .filter(x -> x < 5) // ORDERED 48 | .mapToInt(x-> x) // ORDERED 49 | .sum(); // ORDERED 50 | 51 | System.out.println(sum); 52 | 53 | // output: (for every execution - the output won't change) 54 | // 6 55 | ``` 56 | 57 | ### Chapter 2: Concurrent vs parallel programming 58 | 59 | There are a lot of definitions to _concurrent_ and _parallel_ programming. I will introduce a set of definitions that will serve us best. 60 | 61 | > **Definition 8.1.** **_Cuncurrent programming_** is the ability to solve a task using additional synchronization algorithms. 62 | 63 | > **Definition 8.2.** **_Parallel programming_** is the ability to solve a task without using additional synchronization algorithms. 64 | 65 | Stream library is written using additional synchronization algorithms, but we can use its methods without any. When we write _reducers_ or _collectors_ or make use of the built-in _reducers_/_collectors_ stream gave us, we do not need to use any additional synchronization algorithms to solve our task. 66 | The only thing we need to do is to understand how to split the big problem into smaller tasks. 67 | 68 | The question we need to ask is when do we need to upgrade sequential solution to parallel one? 69 | * You have lot's of data to calculate so the parallel calculation will make a difference. 70 | * Not every problem that can be solved in _Cuncurrent programming_ can be solved with Parallel programming; Splitting a task to independent smaller tasks is not always possible. 71 | * Even if we succeed to split the task into smaller independent tasks, we still need to store our temporary results. Keep in mind the space complexity needed. 72 | 73 | Write each pipeline to support parallelism although it won't be executed in parallel by your or the library choice. 74 | 75 | --- 76 | 77 | ### Chapter 3: Fork/Join framework introduction 78 | 79 | Stream library as other Java's standard libraries using the _common thread pool_ to assign tasks to threads. As its name suggests, it's threads are used by everyone. Keep in mind that if you are using parallel stream on the common thread pool to calculate task that may be stuck because they wait for a server response or they call to I/O blocking operation, then you will stack each part of your system that uses the common thread pool also at the same time. 80 | 81 | With Fork / Join Framework we can create new thread pools. The advantage is solving the problem I introduced above, but the drawback is we may create too many threads that do not work. 82 | 83 | The thread pool assigns tasks to threads which are not busy at the moment. After a thread finishes its task, it will wait for the next task and so on. Each thread pool manages a stuck of tasks (functions) for each of his threads - a thread will take a task from __his__ stuck, and if it's empty, he will take from other thread's stuck. 84 | 85 | The _common thread pool_ contains `N` threads. `N` is equal to the number of cores the computer has `- 1`. The `-1` is for letting the `main` thread to also run without getting into a fight for execution time. 86 | 87 | In this chapter, we won't examine each class and method this library proved but only the relevant for our need. I recommend any reader to examine for himself the parts that are not covered here after reading this tutorial. 88 | 89 | The following `Executors` functions let us create new, different thread pools: 90 | 91 | | `public static ExecutorService newSingleThreadExecutor()` | 92 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 93 | | Create and return a new thread pool with only one thread that will execute the tasks. The thread pool can't be configured to use more than one thread. If the thread is terminated, a new thread will be created. | 94 | 95 | | `public static ExecutorService newFixedThreadPool(int nThreads)` | 96 | | :---------------------------------------------------------------- | 97 | | Create and return a new thread pool containing `nThreads` threads such that each of them takes tasks from __one__ stuck. If any thread is terminated, a new thread will be created. | 98 | -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Quiz.md: -------------------------------------------------------------------------------- 1 | # Java streams - Quiz 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | The Answers are at the end of the quiz. 5 | 6 | ---- 7 | 8 | ###### Question 1 9 | 10 | Name one difference between the following pipes. Do they print the same output? If yes, which version would you prefer - name one reason. 11 | 12 | ```java 13 | Stream.of(1, 2, 3) 14 | .map((Integer number) -> number * 10) 15 | .findFirst() 16 | .ifPresent((Integer number) -> System.out.println(number)); 17 | 18 | Stream.of(1, 10, 100, 1000) 19 | .findFirst() 20 | .map((Integer number) -> number * 10) 21 | .ifPresent((Integer number) -> System.out.println(number)); 22 | ``` 23 | 24 | [Answer 1](#1-question-with-answer) 25 | 26 | ###### Question 2 27 | 28 | Name one difference between the following pipes. Do they print the same output? If yes, which version would you prefer - name one reason. 29 | 30 | ```java 31 | Stream.of(1, 2, 3) 32 | .filter((Integer number) -> number > 1) 33 | .findFirst() 34 | .ifPresent((Integer number) -> System.out.println(number)); 35 | 36 | Stream.of(1, 10, 100, 1000) 37 | .findFirst() 38 | .filter((Integer number) -> number > 1) 39 | .ifPresent((Integer number) -> System.out.println(number)); 40 | ``` 41 | 42 | [Answer 2](#2-question-with-answer) 43 | 44 | ###### Question 3 45 | 46 | Does the following code compile? If yes, what does it print? If not, what is the reason and Java implementors didn't allow it? 47 | ```java 48 | Stream.of(1, 2, 3) 49 | .filter((Integer number) -> number > 1) 50 | .findFirst() 51 | .sorted() 52 | .ifPresent((Integer number) -> System.out.println(number)); 53 | ``` 54 | 55 | [Answer 3](#3-question-with-answer) 56 | 57 | ###### Question 4 58 | 59 | What methods must the `Person` class implement to make the following code works? (I mean, what `sorted` operation invokes in `Person` class?) 60 | 61 | ```java 62 | Stream.of(new Person(1), new Person(2)) 63 | .sorted() 64 | .findFirst() 65 | .ifPresent((Person person) -> System.out.println(person)); 66 | ``` 67 | 68 | [Answer 4](#4-question-with-answer) 69 | 70 | ###### Question 5 71 | 72 | What does the following code prints? Could we made it more readable? 73 | ```java 74 | Predicate p1 = (Integer number) -> number % 2 == 0; 75 | Predicate p2 = (Integer number) -> number % 3 == 0; 76 | 77 | Stream.of(1, 2, 3) 78 | .peek((Integer number) -> System.out.println(number)) 79 | .filter(p1.and(p2)) // <<<----- and 80 | .forEach((Integer number) -> System.out.println(number)); 81 | ``` 82 | 83 | [Answer 5](#5-question-with-answer) 84 | 85 | ###### Question 6 86 | 87 | What does the following code prints? Could we made it more readable? 88 | ```java 89 | Predicate p1 = (Integer number) -> number % 2 == 0; 90 | Predicate p2 = (Integer number) -> number % 3 == 0; 91 | 92 | Stream.of(1, 2, 3) 93 | .peek((Integer number) -> System.out.println(number)) 94 | .filter(p1.or(p2)) // <<<----- or 95 | .forEach((Integer number) -> System.out.println(number)); 96 | ``` 97 | 98 | [Answer 6](#6-question-with-answer) 99 | 100 | ###### Question 7 101 | 102 | What does the following code prints? 103 | ```java 104 | Stream stream1 = Stream.of(1, 2) 105 | .peek((Integer number) -> System.out.println(number)); 106 | 107 | Stream stream2 = Stream.of(1, 2) 108 | .peek((Integer number) -> System.out.println(number)); 109 | 110 | stream1.flatMap(number -> stream2.filter(x -> x != number)) 111 | .forEach((Integer number) -> System.out.println(number)); 112 | ``` 113 | 114 | [Answer 7](#7-question-with-answer) 115 | 116 | ###### Question 8 117 | 118 | How can you improve the readability of the following pipeline: 119 | 120 | ```java 121 | List l1 = Arrays.asList(1,2,3,4,5); 122 | 123 | int sum1 = Arrays.asList(l1,l1,l1) 124 | .stream() 125 | .flatMap(list1 -> list1.stream() 126 | .map((Integer x) -> x * 10) 127 | .peek(System.out::println) 128 | ) 129 | .mapToInt(x->x) 130 | .sum(); 131 | ``` 132 | 133 | [Answer 8](#8-question-with-answer) 134 | 135 | ###### Question 9 136 | 137 | Does both the pipelines print the same elements in the same order? Is it the _encounting order_? 138 | 139 | ```java 140 | List l1 = Arrays.asList(1,1,2,2); 141 | 142 | Arrays.asList(l1,l1,l1) 143 | .stream() 144 | .flatMap(list1 -> list1.stream() 145 | .sorted() 146 | .distinct() 147 | ) 148 | .forEach(System.out::println) 149 | 150 | Arrays.asList(l1,l1,l1) 151 | .stream() 152 | .flatMap(list1 -> list1.stream()) 153 | .sorted() 154 | .distinct() 155 | .forEach(System.out::println) 156 | ``` 157 | 158 | [Answer 9](#9-question-with-answer) 159 | 160 | ###### Question 10 161 | 162 | Does this code compile? 163 | 164 | ```java 165 | List l1 = Arrays.asList(1,1,2,2); 166 | 167 | Arrays.asList(l1,l1,l1) 168 | .stream() 169 | .flatMap(list1 -> list1.stream()) 170 | .mapToInt(Function.identity()) 171 | .forEach(System.out::println); 172 | 173 | // the source code of Function.identity(): 174 | // 175 | // static Function identity() { 176 | // return t -> t; 177 | // } 178 | ``` 179 | 180 | [Answer 10](#10-question-with-answer) 181 | 182 | ###### Question 11 183 | 184 | Can we improve the readability and the safety of the following code? 185 | 186 | ```java 187 | List list1=new ArrayList<>(); 188 | 189 | // list1 is used only after the following code is done. 190 | // your co-worker says that this pipeline has no 191 | // reason/can't run for some reason in parallel. 192 | Stream.of(1,2,3,4,5) 193 | .filter(x->x>3) 194 | .peek(x-> callingHeavyFunction(x)) 195 | .sorted() 196 | .forEach(x-> list1.add(x)); 197 | ``` 198 | 199 | [Answer 11](#11-question-with-answer) 200 | 201 | ###### Question 12 202 | 203 | Write a `Map` collector in the following way (implement the `Collector` interface): 204 | * The keys are the elements from the calling stream. 205 | * The values are `List`. `T` is the type of the elements from the calling stream. 206 | * Each list accept only five items at most. 207 | 208 | [Answer 12](#12-question-with-answer) 209 | 210 | #### Answers: (With the questions) 211 | 212 | ###### 1. Question with Answer 213 | 214 | ###### Question 215 | 216 | Name one difference between the following pipes. Do they print the same output? If yes, which version would you prefer - name one reason. 217 | 218 | ```java 219 | Stream.of(1, 2, 3) 220 | .map((Integer number) -> number * 10) 221 | .findFirst() 222 | .ifPresent((Integer number) -> System.out.println(number)); 223 | 224 | Stream.of(1, 10, 100, 1000) 225 | .findFirst() 226 | .map((Integer number) -> number * 10) 227 | .ifPresent((Integer number) -> System.out.println(number)); 228 | ``` 229 | 230 | ###### Answer 231 | 232 | The difference is while the first pipeline run `map` on `Stream`, the second pipeline run `map` on `Optional`. 233 | 234 | `map` only creates a new stream with new content with each cell. so if `map` operation is running on a `Stream` with 0+ elements or an `Optional` with 0-1 elements, we will get the same result. 235 | 236 | I would prefer the first one because for after the `findFirst` operation, we are not operating on stream anymore, so the operation `findFirst` is a delimiter between `Stream` pipeline and `optional` pipeline. My recommendation is to highlight this delimiter by locating it as low as we can because the amount of operation in `Optional` pipeline is small. 237 | 238 | [Question 2](#question-2) 239 | 240 | ###### 2. Question with Answer 241 | 242 | ###### Question 243 | 244 | Name one difference between the following pipes. Do they print the same output? If yes, which version would you prefer - name one reason. 245 | 246 | ```java 247 | Stream.of(1, 2, 3) 248 | .filter((Integer number) -> number > 1) 249 | .findFirst() 250 | .ifPresent((Integer number) -> System.out.println(number)); 251 | 252 | Stream.of(1, 10, 100, 1000) 253 | .findFirst() 254 | .filter((Integer number) -> number > 1) 255 | .ifPresent((Integer number) -> System.out.println(number)); 256 | ``` 257 | 258 | ###### Answer 259 | 260 | The difference is while the first pipeline run `filter` on `Stream`, the second pipeline run `filter` on `Optional`. 261 | 262 | Both the pipelines calculate different results. The first will print `2` and the second will print nothing. 263 | 264 | [Question 3](#question-3) 265 | 266 | ###### 3. Question with Answer 267 | 268 | ###### Question 269 | 270 | Does the following code compile? If yes, what does it print? If not, what is the reason and Java implementors didn't allow it? 271 | ```java 272 | Stream.of(1, 2, 3) 273 | .filter((Integer number) -> number > 1) 274 | .findFirst() 275 | .sorted() 276 | .ifPresent((Integer number) -> System.out.println(number)); 277 | ``` 278 | 279 | ###### Answer 280 | 281 | The code doesn't compile because `Optional` class doesn't have `sorted` method. The reason for that is because `Optional` instance represents an amount of 0-1 elements, so there is no point in sorting them. 282 | 283 | [Question 4](#question-4) 284 | 285 | ###### 4. Question with Answer 286 | 287 | ###### Question 288 | 289 | What methods must the `Person` class implement to make the following code works? (I mean, what `sorted` operation invokes in `Person` class?) 290 | 291 | ```java 292 | Stream.of(new Person(1), new Person(2)) 293 | .sorted() 294 | .findFirst() 295 | .ifPresent((Person person) -> System.out.println(person)); 296 | ``` 297 | 298 | ###### Answer 299 | 300 | `Person` class need to implement `Comparable` functional interface. 301 | 302 | ```java 303 | public class Person implements Comparable { 304 | private int id; 305 | 306 | public Person(int id) { 307 | this.id = id; 308 | } 309 | 310 | public int getId() { 311 | return id; 312 | } 313 | 314 | @Override 315 | public int compareTo(Person person) { 316 | Objects.requireNonNull(person); 317 | 318 | if (getId() == person.getId()) 319 | return 0; 320 | else if (getId() > person.getId()) 321 | return 1; 322 | return -1; 323 | } 324 | } 325 | ``` 326 | 327 | [Question 5](#question-5) 328 | 329 | ###### 5. Question with Answer 330 | 331 | ###### Question 332 | 333 | What does the following code prints? Could we made it more readable? 334 | ```java 335 | Predicate p1 = (Integer number) -> number % 2 == 0; 336 | Predicate p2 = (Integer number) -> number % 3 == 0; 337 | 338 | Stream.of(1, 2, 3) 339 | .peek((Integer number) -> System.out.println(number)) 340 | .filter(p1.and(p2)) // <<<----- and 341 | .forEach((Integer number) -> System.out.println(number)); 342 | ``` 343 | 344 | ###### Answer 345 | 346 | The above code does not print anything. Only elements which divide by 2 and three will pass the `filter` operation. That means that only items which divided by six will. There any no such elements here, so nothing is printed. 347 | 348 | We could write it in different way (Personally, I would prefer the way it was in the question): 349 | 350 | ```java 351 | Predicate p1 = (Integer number) -> number % 2 == 0; 352 | Predicate p2 = (Integer number) -> number % 3 == 0; 353 | 354 | Stream.of(1, 2, 3) 355 | .peek((Integer number) -> System.out.println(number)) 356 | .filter(p1) 357 | .filter(p2) 358 | .forEach((Integer number) -> System.out.println(number)); 359 | ``` 360 | 361 | In case we are not using `p1` and `p2` anywhere else in our code, we could write the following: 362 | 363 | ```java 364 | Stream.of(1, 2, 3) 365 | .peek((Integer number) -> System.out.println(number)) 366 | .filter((Integer number) -> number % 6 == 0) 367 | .forEach((Integer number) -> System.out.println(number)); 368 | ``` 369 | 370 | [Question 6](#question-6) 371 | 372 | ###### 6. Question with Answer 373 | 374 | ###### Question 375 | 376 | What does the following code prints? Could we made it more readable? 377 | ```java 378 | Predicate p1 = (Integer number) -> number % 2 == 0; 379 | Predicate p2 = (Integer number) -> number % 3 == 0; 380 | 381 | Stream.of(1, 2, 3) 382 | .peek((Integer number) -> System.out.println(number)) 383 | .filter(p1.or(p2)) // <<<----- or 384 | .forEach((Integer number) -> System.out.println(number)); 385 | ``` 386 | 387 | ###### Answer 388 | 389 | It will print: 390 | ```java 391 | 2 392 | 3 393 | ``` 394 | The reason is similar to the last answer. But here we could not break it down to 2 `filter` operations because it will be equal to `and`. 395 | 396 | In case we are not using `p1` and `p2` anywhere else in our code, we could write the following: 397 | 398 | ```java 399 | Stream.of(1, 2, 3) 400 | .peek((Integer number) -> System.out.println(number)) 401 | .filter((Integer number) -> number % 2 == 0 || number % 3 == 0) 402 | .forEach((Integer number) -> System.out.println(number)); 403 | ``` 404 | 405 | [Question 7](#question-7) 406 | 407 | ###### 7. Question with Answer 408 | 409 | ###### Question 410 | 411 | What does the following code prints? 412 | ```java 413 | Stream stream1 = Stream.of(1, 2) 414 | .peek((Integer number) -> System.out.println(number)); 415 | 416 | Stream stream2 = Stream.of(1, 2) 417 | .peek((Integer number) -> System.out.println(number)); 418 | 419 | stream1.flatMap(number -> stream2.filter(x -> x != number)) 420 | .forEach((Integer number) -> System.out.println(number)); 421 | ``` 422 | 423 | ###### Answer 424 | 425 | It would print the following __if and only if__ Java would allow using the same stream (`stream2`) more than once: 426 | ```java 427 | 1 428 | 1 429 | 2 430 | 2 431 | 2 432 | 1 433 | 1 434 | 2 435 | ``` 436 | 437 | But because Java doesn't allow it, then it would print: 438 | ```java 439 | "java.lang.IllegalStateException: stream has already been operated upon or closed.." 440 | ``` 441 | 442 | [Question 8](#question-8) 443 | 444 | ###### 8. Question with Answer 445 | 446 | ###### Question 447 | 448 | How can you improve the readability of the following pipeline: 449 | 450 | ```java 451 | List l1 = Arrays.asList(1,2,3,4,5); 452 | 453 | int sum1 = Arrays.asList(l1,l1,l1) 454 | .stream() 455 | .flatMap(list1 -> list1.stream() 456 | .map((Integer x) -> x * 10) 457 | .peek(System.out::println) 458 | ) 459 | .mapToInt(x->x) 460 | .sum(); 461 | ``` 462 | 463 | ###### Answer 464 | 465 | Each node of `l1` is a list. Inside the `flatMap` method we return every inner list of l1 with a minor change on each element. All in all, all the items in all the inner lists will be changed in the same way so we can do that change outside of the flat map. 466 | 467 | ```java 468 | List l1 = Arrays.asList(1,2,3,4,5); 469 | 470 | int sum1 = Arrays.asList(l1,l1,l1) 471 | .stream() 472 | .flatMap(list1 -> list1.stream()) 473 | .mapToInt((Integer x) -> x * 10) 474 | .peek(System.out::println) 475 | .sum(); 476 | ``` 477 | 478 | [Question 9](#question-9) 479 | 480 | ###### 9. Question with Answer 481 | 482 | ###### Question 483 | 484 | Does both the pipelines print the same elements in the same order? Is it the _encounting order_? 485 | 486 | ```java 487 | List l1 = Arrays.asList(1,1,2,2); 488 | 489 | Arrays.asList(l1,l1,l1) 490 | .stream() 491 | .flatMap(list1 -> list1.stream() 492 | .sorted() 493 | .distinct() 494 | ) 495 | .forEach(System.out::println) 496 | 497 | Arrays.asList(l1,l1,l1) 498 | .stream() 499 | .flatMap(list1 -> list1.stream()) 500 | .sorted() 501 | .distinct() 502 | .forEach(System.out::println) 503 | ``` 504 | 505 | ###### Answer 506 | 507 | No, inside the first pipeline, the `flatMap` flat the following lists: `1,2`,`1,2`,`1,2`to: `1,2,1,2,1,2,1,2` and then print it. The second pipeline sort the elements from all the origin inner __lists__ : `1,1,2,2,1,1,2,2,1,1,2,2` to `1,1,1,1,1,1,2,2,2,2,2,2`and then call `distinct()`: `1,2` and then print it. 508 | 509 | [Question 10](#question-10) 510 | 511 | ###### 10. Question with Answer 512 | 513 | ###### Question 514 | 515 | ```java 516 | List l1 = Arrays.asList(1,1,2,2); 517 | 518 | Arrays.asList(l1,l1,l1) 519 | .stream() 520 | .flatMap(list1 -> list1.stream()) 521 | .mapToInt(Function.identity()) 522 | .forEach(System.out::println); 523 | 524 | // the source code of Function.identity(): 525 | // 526 | // static Function identity() { 527 | // return t -> t; 528 | // } 529 | ``` 530 | 531 | ###### Answer 532 | 533 | The code doesn't compile. `mapToInt` receive a lambda which gets an `Integer` and returns `int`. Since `Integer` isn't `int` then we can't use `Function.identity()`; The parameter type does not equal the return type. 534 | 535 | [Question 11](#question-11) 536 | 537 | ###### 11. Question with Answer 538 | 539 | ###### Question 540 | 541 | Can we improve the readability and the safety of the following code? 542 | 543 | ```java 544 | List list1=new ArrayList<>(); 545 | 546 | // list1 is used only after the following code is done. 547 | // your co-worker says that this pipeline has no 548 | // reason/can't run for some reason in parallel. 549 | Stream.of(1,2,3,4,5) 550 | .filter(x->x>3) 551 | .peek(x-> callingHeavyFunction(x)) 552 | .sorted() 553 | .forEach(x-> list1.add(x)); 554 | ``` 555 | 556 | ###### Answer 557 | 558 | Yes. `list1` is used only after filling him, so there is no reason to declare `list` before the stream. We should convert the stream to a list using `Collectors.toList()`. Also, this code does not support parallelism. Even if `callingHeavyFunction` function does not support parallelism now, it can happen in the future. We should write uniform pipelines. 559 | 560 | ###### 12. Question with Answer 561 | 562 | ###### Question 563 | 564 | Write a `Map` collector in the following way (implement the `Collector` interface): 565 | * The keys are the elements from the calling stream. 566 | * The values are `List`. `T` is the type of the elements from the calling stream. 567 | * Each list accept only five items at most. 568 | 569 | ###### Answer 570 | 571 | --missing-- 572 | 573 | --- 574 | -------------------------------------------------------------------------------- /Java Streams - Series/Java streams - Stream class methods.md: -------------------------------------------------------------------------------- 1 | # Java streams - Stream class methods 2 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) | [Java streams tutorial series](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 3 | 4 | I will refer to `Spliterator` characteristics as flags inside `StreamOpFlag` enum. That is because only the flags defined there are currently used in stream library. 5 | 6 | | `void forEach(Consumer action)` | 7 | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 8 | | The _**forEach**_ method will run _action_ function on each element in the stream. The order of elements which sent to `action` is not defined in parallel execution. Also using this method in sequential execution, it is best practice to assume the order of elements which sent to `action` is not defined as well.| 9 | 10 | | Terminal operation | 11 | | :------------------: | 12 | 13 | | Stateless operation| 14 | | :-----------------:| 15 | 16 | ```java 17 | // example: 18 | 19 | Arrays.asList(1,2,3) 20 | .parallelStream() 21 | .forEach(System.out::println); 22 | 23 | // possible output: 24 | // 3 25 | // 1 26 | // 2 27 | ``` 28 | | `void forEachOrdered(Consumer action)` | 29 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 30 | | The _**forEachOrdered**_ method will run _action_ function on each element in the stream and the order which elements from the calling stream are sending to `action` is defined by _encounting order_ if exist. Else the order of elements in the calling stream. Note: If element `n` (by order of the calling stream) did not reach yet to the `forEachOrdered` operation, any other element `m > n` which came to `forEachOrdered` will have to wait. | 31 | 32 | | Terminal operation | 33 | | :------------------: | 34 | 35 | | Statelful operation| 36 | | :-----------------:| 37 | 38 | ```java 39 | // example 1: 40 | 41 | Arrays.asList(1,2,3) 42 | .parallelStream() 43 | // the encounting order is still 1,2,3 44 | .forEachOrdered(System.out::println); 45 | 46 | // output: 47 | // 1 48 | // 2 49 | // 3 50 | 51 | // example 2: 52 | 53 | Arrays.asList(3,1,2) 54 | .parallelStream() 55 | // encounting order is 3,1,2 56 | .sorted() 57 | // encounting order is 1,2,3 because sorted operation determine new order. 58 | .forEachOrdered(System.out::println); 59 | 60 | // output: 61 | // 1 62 | // 2 63 | // 3 64 | ``` 65 | | ` Stream map(Function mapper)` | 66 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 67 | | The _**map**_ method is meant to create from each element in the stream a new element. The type of the new element can be different from the old element. | 68 | 69 | | Modify flags: | `DISTINCT` - `C` | `SORTED` - `C` | 70 | | :------------: | :---------------:| :--------------: | 71 | 72 | | Intermediate operation | 73 | | :----------------------: | 74 | 75 | | Stateless operation| 76 | | :-----------------:| 77 | 78 | ```java 79 | // example 1: 80 | 81 | Arrays.asList(1,2,3) 82 | .stream() 83 | .map((Integer x)->x+4) 84 | .forEach(System.out::println); 85 | 86 | // output: 87 | // 5 88 | // 6 89 | // 7 90 | 91 | // example 2: 92 | 93 | collection1.stream() 94 | .map((Integer x)->"hi"+x) 95 | .forEach(System.out::println); 96 | 97 | // output: 98 | // hi1 99 | // hi2 100 | // hi3 101 | ``` 102 | 103 | | `Stream filter(Predicate predicate)` | 104 | | :--- | 105 | | The _**filter**_ operation will determine for each element in the stream if that element will stay or not. The method will run on each element in the stream and check using a condition specified in the _predicate_ function if the element should be in the next stream. The next stream will contain all the elements from the last stream that _predicate_ return true for them. | 106 | 107 | | Modify flags: | `SIZED` - `C` | 108 | | :------------: | :------------:| 109 | 110 | | Intermediate operation | 111 | | :----------------------:| 112 | 113 | | Stateless operation| 114 | | :-----------------:| 115 | 116 | ```java 117 | // example: 118 | 119 | Arrays.asList(1,2,3).stream() 120 | .filter((Integer x)-> x > 1) 121 | .forEach(System.out::println); 122 | 123 | // output: 124 | // 2 125 | // 3 126 | ``` 127 | 128 | | `Stream peek(Consumer action)` | 129 | | :--- | 130 | | _**Peek**_ will run an action on each element of the stream and will return a stream containing the same elements. This operation is mainly to support debugging. For example, we can print the elements after each operation in the pipeline to see how the stream is calculating the elements. Also, it can be used for _side effects_. | 131 | 132 | | Intermediate operation | 133 | | :----------------------:| 134 | 135 | | Stateless operation| 136 | | :-----------------:| 137 | 138 | ```java 139 | // example: 140 | 141 | Arrays.asList("aaa","bbb") 142 | .stream() 143 | .filter((String str1)->str1.contains("a")) 144 | .peek(System.out::println) 145 | .map((String str1)->str1.concat("ccc")) 146 | .forEach(System.out::println); 147 | 148 | // output: 149 | // aaa 150 | // aaaccc 151 | ``` 152 | 153 | | `Stream sorted()` | 154 | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 155 | | The _**sorted**_ method is an intermediate operation and it will create a new stream in which all his elements are sorted according to by natural order. `T` must implement _Comparable_ interface so you can override `int Comparable.compareTo(T o)`. The `sorted` method can't send every element it gets to the next operation in the pipeline because the order of the elements is matters and there is a chance that `sorted` will receive element in the future with smaller value, so this element should be sent first to the next operation in the pipeline. `sorted` use a temporary collection to store all the elements it gets and he starts sorting them from the time it gets executed. | 156 | Notes: 157 | 1. If the calling stream is sorted by any other order, then this method will clear the `SORTED` flag and re-inject it after it sorts the incoming elements by natural order. 158 | 2. When `ORDERED` flag is on, For every two elements which are equal by natural order, the first element appears in the encounter order will enter to the output stream and the second will be filtered out. 159 | 160 | | Modify flags: | `SORTED` - `CI`| `ORDERED` - `I` | 161 | | :------------: | :------------: | :------------: | 162 | 163 | | Intermediate operation | 164 | | :----------------------:| 165 | 166 | | Statelful operation| 167 | | :-----------------:| 168 | 169 | ```java 170 | // example: 171 | 172 | Arrays.asList(1,2,3,1,4).stream() 173 | .filter((Integer x)-> x>1) 174 | .sorted() 175 | .forEach(System.out::println); 176 | 177 | // Out put: 178 | // 2 179 | // 3 180 | // 4 181 | ``` 182 | ![](http://imgur.com/NJI3wlo.jpg) 183 | 184 | | `Stream limit(long maxSize)` | 185 | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 186 | | The _**limit**_ method is an intermediate operation that will create a new stream contains at most `n` elements where `n`=`maxSize`. When `n` elements passed him, or the last operation can't give more to `limit`, `limit` will end the execution of the **all** the stream. When `ORDERED` flag is on, `limit` will wait for the first `n` elements in the encounter order. It means that in case every element entered the `limit` operation except the first `n` elements, all those elements will wait there until the first `n` elements in the encounter order will come or `m` elements from the first `n` will be filtered out during the process until the `limit` operation. In this case, the first `m` elements after the first `n` elements in the encounter order will pass the `limit` operation. | 187 | 188 | | Modify flags: | `SIZED` - `C`| `SHORT_CIRCUIT` - `I`| 189 | | :------------: | :-----------:| :-------------------:| 190 | 191 | | Intermediate operation | 192 | | :----------------------:| 193 | 194 | | Statelful operation | 195 | | :-----------------: | 196 | 197 | ```java 198 | // example 1: 199 | 200 | Arrays.asList(1,2,3,4,5).stream() 201 | .limit(2) 202 | .filter((Integer x)-> x > 1) 203 | .forEach(System.out::println); 204 | 205 | // Out put: 206 | // 2 207 | ``` 208 | 209 | ![](http://imgur.com/ciubvZl.jpg) 210 | 211 | ```java 212 | // example 2: (filter and limit swapped) 213 | 214 | Arrays.asList(1,2,3,4,5).stream() 215 | .filter((Integer x)-> x > 1) 216 | .limit(2) 217 | .forEach(System.out::println); 218 | 219 | // Out put: 220 | // 2 221 | ``` 222 | 223 | ![](http://imgur.com/oiDX6lN.jpg) 224 | 225 | | ` A[] toArray(IntFunction generator)` | 226 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 227 | | The _**toArray**_ method is a terminal operation that will return a new array of type `A` containing all the elements from the last operation in the pipeline. If `SIZED` flag is on, then the size of the generated array is known when `toArray` operation starts. In this case, it will initialize an array with the exact amount of cells needed. If `SIZED` is off then `toArray` will guess how many spaces it needs in the array and it may be a case when he initializes an array with fewer cells then he needs so multiple initializations will be done. Each time it will copy the elements from the last array to the new array. `generator` receives Integer `n` and must return `A[]`. The array length must be at list equal to `n`. | 228 | 229 | | Teminal operation| 230 | | :---------------:| 231 | 232 | | Statelful operation | 233 | | :-----------------: | 234 | 235 | ```java 236 | // example: 237 | 238 | Integer[] array=Arrays.asList(3,2,1).stream() 239 | .sorted() 240 | // the following line is eqivalent to: 241 | //.toArray(Integer[]::new); 242 | .toArray((int n)->new Integer[n]); 243 | 244 | Arrays.stream(array).forEach(System.out::println); 245 | 246 | // output: 247 | // 1 248 | // 2 249 | // 3 250 | ``` 251 | 252 | | `IntStream mapToInt(ToIntFunction mapper)` | 253 | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 254 | | Same as `map` operation, this method receive a function `mapper` whos return type is `Integer`. The return stream is a special stream with built-in functions to deal with Integer elements. | 255 | 256 | | Modify flags: | `DISTINCT` - `C`| `SORTED` - `C`| 257 | | :------------: | :--------------:| :------------:| 258 | 259 | | Intermediate operation | 260 | | :----------------------:| 261 | 262 | | Stateless operation | 263 | | :-----------------: | 264 | 265 | ```java 266 | // example: 267 | 268 | Arrays.asList(3,2,1).stream() 269 | // notice that map get function with Integer 270 | // parameter because the parameter type is 271 | // generic and the return type must be 272 | // int because we convert the stream to IntStream. 273 | // the following line is equivalent to: 274 | // .mapToInt(Integer::intValue) 275 | .mapToInt((Integer x)-> x) 276 | // notice that map get function with int 277 | // parameter instead of Integer and the 278 | // return type must be int. 279 | .map((int x)->x*10) 280 | .forEach(System.out::println); 281 | 282 | // output: 283 | // 30 284 | // 20 285 | // 10 286 | ``` 287 | 288 | | `Optional findAny()` | 289 | | :--| 290 | | The _**findAny**_ method is a terminal operation that will return one element from the caller stream inside an `Optional` object. This operation may return a different element for each execution without giving any consideration to the encounter order (if it exists). In case the caller stream is empty for any reason, return an empty `Optional` object. This operation has much better performance than `findFirst` because it will return the first element came to it and it does not guarantee to return the first element in the calling stream. 291 | 292 | | Modify flags: | `ORDERED` - `C`| `SHORT_CIRCUIT` - `I`| 293 | | :------------: | :-------------:| :-------------------:| 294 | 295 | | Terminal operation| 296 | | :----------------:| 297 | 298 | | Stateless operation | 299 | | :-----------------: | 300 | 301 | ```java 302 | // example: 303 | 304 | Arrays.asList(14,13,12,11,10) 305 | .stream() 306 | .sorted() 307 | .findAny() 308 | .map((Integer element)-> element * element) 309 | .ifPresent(System.out::println); 310 | 311 | // possible output: 312 | // 100 313 | ``` 314 | 315 | | `T reduce(T identity, BinaryOperator accumulator)` | 316 | | :--- | 317 | | In a synchronized execution, the **_reduce_** operation use the _identity_ value only once as an initial temporary result. The calculating is the same as the first overload we saw. In case of parallel running, it will work as described above. In case the calling stream doesn't have any elements, the `reduce` method return the _identity_ value as a result. | 318 | 319 | | Terminal operation| 320 | | :----------------:| 321 | 322 | | Statelful operation | 323 | | :-----------------: | 324 | 325 | ``` java 326 | // example: finding max. 327 | 328 | Integer result = Arrays.asList(2,3,4,5,6) 329 | .stream() 330 | .reduce(Integer.MIN_VALUE, (Integer resultUntilNow, Integer element)-> 331 | Math.max(resultUntilNow,element)); 332 | System.out.println(result); 333 | 334 | // output: 335 | // 6 336 | ``` 337 | ![](http://i.imgur.com/2CUx0Cd.jpg) 338 | 339 | | ` U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)` | 340 | | :--- | 341 | | In a synchronized execution running, the _**reduce**_ operation uses the _identity_ value only once as an initial temporary result. The _identity_ type can be different from the elements in the calling stream. The calculating is the same as the first overload we saw. In case of parallel running, it will work as described above. In case the calling stream as no elements, return the _identity_ value as a result. | 342 | 343 | | Terminal operation| 344 | | :----------------:| 345 | 346 | | Statelful operation | 347 | | :-----------------: | 348 | 349 | ```java 350 | // example: joining all elements 351 | 352 | String result = Arrays.asList(2,3,4,5,6) 353 | .stream() 354 | .reduce("", (String resultUntilNow, Integer element)-> resultUntilNow+element, 355 | (String partialResult1,String partialResult2)->partialResult1.concat(partialResult2)); 356 | 357 | System.out.println(result); 358 | 359 | // output: 360 | // 23456 361 | ``` 362 | -------------------------------------------------------------------------------- /Java Streams - Series/README.md: -------------------------------------------------------------------------------- 1 | # Java Streams In Depth 2 | 3 | #### [Stav Alfi](https://github.com/stavalfi) | [Lectures](https://github.com/stavalfi/lectures) 4 | 5 | ### Chapters: 6 | 7 | 1. [What is a stream?](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%201%20-%20What%20is%20a%20java%20stream.md) 8 | 2. [Primitive steams](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%202%20-%20Primitive%20steams.md) 9 | 3. [Optional class](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%203%20-%20Optional%20class.md) 10 | 4. [Reduction](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%204%20-%20Reduction.md) 11 | 5. [Collectors](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%205%20-%20Collectors.md) 12 | 6. [Spliterator](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%206%20-%20Spliterator.md) 13 | 7. [Parallel Streams](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Part%207%20-%20Parallel%20Streams.md) 14 | 15 | 16 | ### Additional 17 | 18 | 1. [Introduction](#introduction) 19 | 2. [Quiz](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Quiz.md) 20 | 3. [Complete terms table](#complete-terms-table) 21 | 4. [Spliterator characteristics table](#spliterator-characteristics-table) 22 | 5. [Collections characteristics table](#collections-characteristics-table) 23 | 6. [Stream methods characteristics table](#stream-methods-characteristics-table) 24 | 7. [Stream class methods](https://github.com/stavalfi/lectures/blob/master/Java%20Streams%20-%20Series/Java%20streams%20-%20Stream%20class%20methods.md) 25 | 8. [Collectors class methods](#collectors-class-methods) 26 | 9. [Spliterator interface methods](#spliterator-interface-methods) 27 | 10. [Optional class methods](#optional-class-methods) 28 | 11. [Legal](#legal) 29 | 30 | ---- 31 | 32 | ### Introduction 33 | 34 | In this tutorial, we will cover the stream library from the basic operations and learn each relevant classes. The tutorial designates to developers with absolutely no experience with streams to more experienced developers who want to clarify their knowledge. Throughout this series, I will introduce new phrases and explain more deeply each Java stream method. 35 | 36 | At the end of the tutorial, the reader will have all the necessary information about how each operation works and how to build a query that uses everything stream can give you. 37 | 38 | **Requirements** 39 | 40 | It is highly recommended that you will have basic knowledge about templates 41 | Also, a full understanding of lambda expressions is a must. 42 | 43 | [Lambda Expressions In Depth By Stav Alfi](https://gist.github.com/stavalfi/e24178288973d104042d4162a02fd135) 44 | 45 | --- 46 | 47 | ### Complete terms table 48 | 49 | > **Definition 1.1.** _**Pipeline**_ is a couple of methods that will be executed by a specific order. 50 | 51 | > **Definition 1.2.** _**Intermidiate operations**_ will be located everywhere in the stream expect at the end. They return a stream object and does not execute any procedure in the pipeline. 52 | 53 | > **Definition 1.3.** _**terminal operations**_ will be located only at the end of the stream. They execute the pipeline. They do not return stream object so no other_Intermidiate operations_ or _terminal operations_ can be added after them. 54 | 55 | > **Definition 1.4.** Intermediate operations will be called _**short-circuiting operation**_ if that operation produces a new stream with a finite amount of elements from `n` elements where `n` can be an infinite number. 56 | 57 | > **Definition 1.5.** Terminal operations will be called _**short-circuiting operation**_ if it can finish his execution after a finite amount of time. 58 | 59 | > **Definition 5.1.** **_Reduce-left_** operation determine the first temporary result will be the first element in the collection from the left and the reduce operation will visit each item in the collection that he didn't visit yet from left to right. 60 | 61 | > **Definition 5.2.** **_Reduce-right_** operation determine the first temporary result will be the first element in the collection from the right, and the reduce operation will visit each item in the collection that he didn't visit yet from right to left. 62 | 63 | > **Definition 8.1.** **_Cuncurrent programming_** is the ability to solve a task using additional synchronization algorithms. 64 | 65 | > **Definition 8.2.** **_Parallel programming_** is the ability to solve a task without using additional synchronization algorithms. 66 | 67 | ###### Aditional definitions 68 | 69 | > **Definition 1.** A function or expression is said to have a ___side effect___ if it modifies some state outside its scope or has an observable interaction with its calling functions or the outside world besides returning a value. 70 | 71 | > **Definition 2.** A function may be considered a ___pure function___ if both of the following statements about the function hold: 72 | > 1. The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while a program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. 73 | > 74 | >2. Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices. 75 | 76 | > **Definition 3.** ___Lambda Expression___ equals to object of a local class implements an existing _Functional Interface_. The lambda is the implementation of the single instance method in that interface. _Lambda Expression_ is a function with zero or more parameters and a body that will be (or not) executed at a later stage. We have access to its _free variables_ inside the body. 77 | 78 | --- 79 | 80 | ### Spliterator characteristics table 81 | 82 | | Characteristic| | 83 | | :-------------| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 84 | | `CONCURRENT` | It's possible to modify (delete/insert/replace elements) the source of the spliterator concurrently without any additional synchronization. 85 | | `NONNULL` | The source of the spliterator can't insert null elements, so each of the elements is guaranteed to be a non-null value. | 86 | | `IMMUTABLE` | The source of the spliterator prohibit modification (delete/insert/replace elements). | 87 | | `DISTINCT` | For each 2 different elements `x` and `y` in the source of the spliterator we can tell that `x.equals(y) == false`. | 88 | | `ORDERED` | If we print the elements in the source of the spliterator multiple times by iterating it, we will print the elements in the same order time after time. That means all the elements are stored in the source of the spliterator in a specific order. We can refer to that situation by specifying that the source of the spliterator has _encounting order_. For example: `Array`, `List`,`Stuck` has _encounting order_ but `HashMap` doesn't. We can't iterate over `HashMap`. | 89 | | `SORTED` | The source of the spliterator is ordered by a comparator or in the natural order. | 90 | | `SIZED` | We know the estimated amount of iterations left in the spliterator. | 91 | | `SUBSIZED` | If we split the task into two chunks, we would know the estimated amount of iterations each spliterator would have. Note: If `SUBSIZED` is on, then `SIZED` also. The reason is if we know how many iterations will be needed after the split for each spliterator, we must know first how many iterations left without splitting in the first place. The claim doesn't follow for the opposite direction as mentioned above. For example - binary trees. | 92 | 93 | --- 94 | 95 | ### Collections characteristics table 96 | 97 | The following table list all the characteristics of each collection's spliterator. 98 | 99 | | |`ORDERED`| `DISTINCT` | `SORTED` | `SIZED` | `NONULL` | `IMMUTABLE` | `CONCURRENT`| `SUBSIZED` | 100 | | :----------------------- |:-------:| :----------:| :----------:| :----------:| :----------:| :----------:| :----------:| :----------:| 101 | |`Stream.of`|`I` | | | `I` | | `I` | | `I` | 102 | |`Arrays.asList`|`I` | | | `I` | | | | `I` | 103 | |`HashSet`| | `I` | | `I` | | | | | 104 | |`ArrayList`|`I` | | | `I` | | | | `I` | 105 | |`ArrayDeque`|`I` | | | `I` | `I` | | | `I` | 106 | |`ArrayBlockingQueue`|`I` | | | | `I` | | `I` | | 107 | |`ArrayDeque`|`I` | | | `I` | `I` | | | `I` | 108 | |`ConcurrentLinkedDeque`|`I` | | | | `I` | | `I` | | 109 | |`ConcurrentLinkedQueue`|`I` | | | | `I` | | `I` | | 110 | |`DelayQueue`| | | | `I` | | | | `I` | 111 | |`CopyOnWriteArraySet`| | `I` | | `I` | | `I` | | `I` | 112 | |`CopyOnWriteArrayList`|`I` | | | `I` | | `I` | | `I` | 113 | |`ConcurrentSkipListSet`|`I` | `I` | `I` | | `I` | | `I` | | 114 | |`LinkedBlockingDeque`|`I` | | | | `I` | | `I` | | 115 | |`LinkedBlockingQueue`|`I` | | | | `I` | | `I` | | 116 | |`LinkedHashSet`|`I` | `I` | | `I` | | | | `I` | 117 | |`LinkedList`|`I` | | | `I` | | | | `I` | 118 | |`Stack`|`I` | | | `I` | | | | `I` | 119 | |`RoleUnresolvedList`|`I` | | | `I` | | | | `I` | 120 | |`RoleList`|`I` | | | `I` | | | | `I` | 121 | |`PriorityQueue`| | | | `I` | `I` | | | `I` | 122 | |`PriorityBlockingQueue`| | | | `I` | `I` | | | `I` | 123 | |`LinkedTransferQueue`|`I` | | | | `I` | | `I` | | 124 | |`SynchronousQueue`| | | | `I` | | | | `I` | 125 | |`TreeSet`|`I` | `I` | `I` | `I` | | | | | 126 | |`Vector`|`I` | | | `I` | | | | `I` | 127 | 128 | * `I` - Injects. 129 | 130 | --- 131 | 132 | ### Stream methods characteristics table 133 | 134 | The following table shows which characteristics and flags each _intermediate operation_ may turn on and off: (`SHORT_CIRCUIT` is relevant only in the context of `StreamOpFlag` flags) 135 | 136 | | | DISTINCT | SORTED | ORDERED | SIZED | SHORT_CIRCUIT | 137 | | ---------------- | ----------| --------| ---------| -------| ---------------| 138 | | `filter` | | | | `C` | | 139 | | `forEach` | | | `C` | | | 140 | | `forEachOrdered` | | | | | | 141 | | `allMatch` | | | `C` | | `I` | 142 | | `distinct` | `I` | | | `C` | | 143 | | `flatMap` | `C` | `C` | | `C` | | 144 | | `anyMatch` | | | `C` | | `I` | 145 | | `collect` | | | | | | 146 | | `unOrdered` | | | `C` | | | 147 | | `count` | `C` | `C` | `C` | `C` | | 148 | | `findAny` | | | `C` | | `I` | 149 | | `findFirst` | | | | | `I` | 150 | | `flatMapToXXX` | `C` | `C` | | `C` | | 151 | | `limit` | | | | `C` | `I` | 152 | | `map` | `C` | `C` | | | | 153 | | `mapToXXX` | `C` | `C` | | | | 154 | | `max` | | | | | | 155 | | `min` | | | | | | 156 | | `noneMatch` | | | `C` | | `I` | 157 | | `peek` | | | | | | 158 | | `reduce` | | | | | | 159 | | `skip` | | | `C` | `I` | | 160 | | `sorted` | | `I` | `I` | | | 161 | | `toArray` | | | | | | 162 | 163 | * `C` - May clears. 164 | * `I` - May injects. 165 | --- 166 | 167 | ### Collectors class methods 168 | 169 | ------ 170 | 171 | ### Spliterator interface methods 172 | 173 | ---- 174 | 175 | ### Optional class methods 176 | 177 | ---- 178 | 179 | ### Legal 180 | 181 | © Stav Alfi, 2018. Unauthorized use or duplication of this material without express and written permission from the owner is strictly prohibited. Excerpts and links may be used, provided that full and clear 182 | credit is given to Stav Alfi with appropriate and specific direction to the original content. 183 | 184 | Creative Commons License "Streams In Depth" by Stav Alfi is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License.](http://creativecommons.org/licenses/by-nc/4.0/) 185 | Based on a work at https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series. 186 | 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains tutorials on various topics. 2 | 3 | 4 | #### [Functional Programming In JS - Compositions And Transducers](https://github.com/stavalfi/lectures/blob/master/Functional%20Programming%20In%20JS%20-%20Compositions%20And%20Transducers.md) 5 | Throughout this tutorial, we will cover a series of basic technics for manipulating a collection of functions. We will build a utility that processes a single element using composition of functions. Then we will process a collection using multiple implementations such that each of them can do more than the last. 6 | 7 | #### [Java Streams In Depth](https://github.com/stavalfi/lectures/tree/master/Java%20Streams%20-%20Series) 8 | In this tutorial, we will cover the stream library from the basic operations and learn each relevant classes. The tutorial designates to developers with absolutely no experience with streams to more experienced developers who want to clarify their knowledge. Throughout this series, we will introduce new phrases and explain more deeply each Java stream method. 9 | 10 | At the end of the tutorial, the reader will have all the necessary information about how each operation works and how to build a query that uses everything stream can give you. 11 | 12 | #### [Functional Programming in Java 8 - Basic Concepts and Lambdas](https://github.com/stavalfi/lectures/blob/master/Functional%20Programming%20in%20Java%208%20-%20Basic%20Concepts%20and%20Lambdas.md) 13 | This article is meant to build a common language with the reader which will be used to answer the following questions: What are _free variables_? Are we allowed to change them inside the lambda expression? Is it considered dangerous to mutate them? 14 | 15 | #### [Introduction to Git](https://github.com/stavalfi/lectures/blob/master/Introduction%20To%20Git.md) 16 | 17 | 18 | 19 | The tutorial is intended for programmers that want to dive deep and understand what is going on behind the scene. After reading and practicing you should be able to manipulate and understand more advanced articles online about other topics that are not mentioned here. 20 | 21 | #### [Git Cherry Picking](https://github.com/stavalfi/lectures/blob/master/Git%20Cherry%20Picking.md) 22 | 23 | 24 | 25 | The goal of this tutorial is for explaining what cherry-pick command is, how does it work and how to handle errors (conflicts). 26 | 27 | #### [Introduction To Docker](https://github.com/stavalfi/lectures/blob/master/Introduction%20To%20Docker.md) 28 | 29 | ![](https://www.docker.com/sites/default/files/Whale%20Logo332_5.png) 30 | 31 | In this article, we will define what docker is, and it's main components. 32 | 33 | #### [Cpp lvalue, rvalue And Between](https://github.com/stavalfi/lectures/blob/master/Cpp%20lvalue%20rvalue%20and%20between.md) 34 | This tutorial attempts to clarify the common mistakes about the multiple invalid definitions for lvalue and rvalue expressions. 35 | -------------------------------------------------------------------------------- /images/Git - cherry picking/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/1.jpg -------------------------------------------------------------------------------- /images/Git - cherry picking/1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/1.psd -------------------------------------------------------------------------------- /images/Git - cherry picking/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/2.jpg -------------------------------------------------------------------------------- /images/Git - cherry picking/2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/2.psd -------------------------------------------------------------------------------- /images/Git - cherry picking/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/3.jpg -------------------------------------------------------------------------------- /images/Git - cherry picking/3.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Git - cherry picking/3.psd -------------------------------------------------------------------------------- /images/Introduction To Docker/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Introduction To Docker/1.jpg -------------------------------------------------------------------------------- /images/Introduction To Docker/1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Introduction To Docker/1.psd -------------------------------------------------------------------------------- /images/Java streams in depth/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/1.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/1.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/1.psd -------------------------------------------------------------------------------- /images/Java streams in depth/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/2.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/2.psd -------------------------------------------------------------------------------- /images/Java streams in depth/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/3.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/3.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/3.psd -------------------------------------------------------------------------------- /images/Java streams in depth/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/4.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/4.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/4.psd -------------------------------------------------------------------------------- /images/Java streams in depth/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/5.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/5.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/5.psd -------------------------------------------------------------------------------- /images/Java streams in depth/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/6.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/6.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/6.psd -------------------------------------------------------------------------------- /images/Java streams in depth/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/8.jpg -------------------------------------------------------------------------------- /images/Java streams in depth/8.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stavalfi/lectures/85699dc70b8870bf64818dcaaa1e4b3e6c76c63d/images/Java streams in depth/8.psd --------------------------------------------------------------------------------