Skip to content

Commit 5b4db17

Browse files
author
turingfly
committed
Functional Programming
1 parent 031d209 commit 5b4db17

8 files changed

+537
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package functionalProgramming;
2+
3+
import java.time.LocalDate;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
import java.util.function.BiConsumer;
7+
import java.util.function.BiFunction;
8+
import java.util.function.BiPredicate;
9+
import java.util.function.BinaryOperator;
10+
import java.util.function.Consumer;
11+
import java.util.function.Function;
12+
import java.util.function.Predicate;
13+
import java.util.function.Supplier;
14+
import java.util.function.UnaryOperator;
15+
16+
/**
17+
*
18+
* @author chengfeili
19+
* Jun 8, 2017 10:31:11 AM
20+
*
21+
* A functional interface has exactly one abstract method. This doesn't
22+
* mean that they have only one method. It can still contain default
23+
* methods or static methods
24+
*
25+
*/
26+
public class BuiltInFunctionalInterfaces {
27+
28+
/**
29+
* A Supplier is used when you want to generate or supply values without
30+
* taking any input. A Supplier is often used when constructing new objects.
31+
*/
32+
public void supplier() {
33+
Supplier<LocalDate> s1 = LocalDate::now;
34+
Supplier<LocalDate> s2 = () -> LocalDate.now();
35+
LocalDate d1 = s1.get();
36+
LocalDate d2 = s2.get();
37+
System.out.println(d1);
38+
System.out.println(d2);
39+
}
40+
41+
/**
42+
* You use a Consumer when you want to do something with a parameter but not
43+
* return any- thing. BiConsumer does the same thing except that it takes
44+
* two parameters.
45+
*/
46+
public void consumerAndBiconsumer() {
47+
// Consumer
48+
Consumer<String> c1 = System.out::println;
49+
Consumer<String> c2 = x -> System.out.println(x);
50+
c1.accept("a");
51+
c2.accept("a");
52+
53+
// BiConsumer
54+
Map<String, Integer> map = new HashMap<>();
55+
BiConsumer<String, Integer> b1 = map::put;
56+
BiConsumer<String, Integer> b2 = (k, v) -> map.put(k, v);
57+
b1.accept("chicken", 7);
58+
b2.accept("chick", 1);
59+
System.out.println(map);
60+
}
61+
62+
/**
63+
* Predicate is often used when filtering or matching
64+
*/
65+
public void predicateAndBiPredicate() {
66+
// Predicate
67+
Predicate<String> p1 = String::isEmpty;
68+
Predicate<String> p2 = x -> x.isEmpty();
69+
System.out.println(p1.test(""));
70+
System.out.println(p2.test(""));
71+
72+
// BiPredicate
73+
BiPredicate<String, String> b1 = String::startsWith;
74+
BiPredicate<String, String> b2 = (string, prefix) -> string.startsWith(prefix);
75+
System.out.println(b1.test("chicken", "chick"));
76+
System.out.println(b2.test("chicken", "chick"));
77+
78+
// default method
79+
Predicate<String> egg = s -> s.contains("egg");
80+
Predicate<String> brown = s -> s.contains("brown");
81+
Predicate<String> brownEggs = egg.and(brown);
82+
Predicate<String> otherEggs = egg.and(brown.negate());
83+
System.out.println(brownEggs.test("egg brown"));
84+
System.out.println(otherEggs.test("egg"));
85+
}
86+
87+
/**
88+
* A Function is responsible for turning one parameter into a value of a
89+
* potentially different type and returning it. Similarly, a BiFunction is
90+
* responsible for turning two parameters into a value and returning it.
91+
*/
92+
public void functionAndBiFunction() {
93+
// Function
94+
Function<String, Integer> f1 = String::length;
95+
Function<String, Integer> f2 = x -> x.length();
96+
System.out.println(f1.apply("cluck")); // 5
97+
System.out.println(f2.apply("cluck")); // 5
98+
99+
// BiFunction
100+
BiFunction<String, String, String> b1 = String::concat;
101+
BiFunction<String, String, String> b2 = (string, toAdd) -> string.concat(toAdd);
102+
System.out.println(b1.apply("baby ", "chick")); // baby chick
103+
System.out.println(b2.apply("baby ", "chick")); // baby chick
104+
105+
// Creating your own Functional Interface
106+
// interface TriFunction<T,U,V,R>{R apply(T t,U u,V v);}
107+
}
108+
109+
/**
110+
*
111+
* UnaryOperator and BinaryOperator are a special case of a function. They
112+
* require all type parameters to be the same type.
113+
*/
114+
public void unaryOperatorAndBinaryOperator() {
115+
// UnaryOperator
116+
UnaryOperator<String> u1 = String::toUpperCase;
117+
UnaryOperator<String> u2 = x -> x.toUpperCase();
118+
System.out.println(u1.apply("chirp"));
119+
System.out.println(u2.apply("chirp"));
120+
121+
// BuiltInFunctionalInterfaces
122+
BinaryOperator<String> b1 = String::concat;
123+
BinaryOperator<String> b2 = (string, toAdd) -> string.concat(toAdd);
124+
System.out.println(b1.apply("baby ", "chick")); // baby chick
125+
System.out.println(b2.apply("baby ", "chick")); // baby chick
126+
}
127+
128+
public static void main(String[] args) {
129+
BuiltInFunctionalInterfaces b = new BuiltInFunctionalInterfaces();
130+
b.supplier();
131+
b.consumerAndBiconsumer();
132+
b.predicateAndBiPredicate();
133+
}
134+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package functionalProgramming;
2+
3+
import java.util.Optional;
4+
5+
/**
6+
*
7+
* @author chengfeili
8+
* Jun 8, 2017 12:46:14 PM
9+
*
10+
*/
11+
public class ReturningAnOptional {
12+
public static Optional<Double> average(int... scores) {
13+
if (scores.length == 0) {
14+
return Optional.empty();
15+
}
16+
int sum = 0;
17+
for (int score : scores)
18+
sum += score;
19+
return Optional.of((double) sum / scores.length);
20+
}
21+
22+
public static void main(String[] args) {
23+
System.out.println(average(90, 100)); // Optional[95.0]
24+
System.out.println(average()); // Optional.empty
25+
26+
Optional<Double> opt = average(90, 100); if (opt.isPresent())
27+
System.out.println(opt.get()); // 95.0
28+
}
29+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package functionalProgramming;
2+
3+
import java.util.Arrays;
4+
import java.util.Comparator;
5+
import java.util.List;
6+
import java.util.stream.Stream;
7+
8+
/**
9+
*
10+
* @author chengfeili
11+
* Jun 8, 2017 10:36:14 PM
12+
*
13+
* Unlike a terminal operation, intermediate operations deal with
14+
* infinite streams simply by returning an infinite stream
15+
*/
16+
public class StreamCommonIntermediateOprations {
17+
18+
public void test() {
19+
// filter()
20+
Stream<String> s = Stream.of("monkey", "gorilla", "bonobo");
21+
s.filter(x -> x.startsWith("m")).forEach(System.out::print); // monkey
22+
23+
// distinct()
24+
Stream<String> sDistinct = Stream.of("duck", "duck", "duck", "goose");
25+
sDistinct.distinct().forEach(System.out::print); // duckgoose
26+
27+
// limit() and skip()
28+
Stream<Integer> sSkipLimit = Stream.iterate(1, n -> n + 1);
29+
sSkipLimit.skip(5).limit(2).forEach(System.out::print); // 67
30+
31+
// map()
32+
Stream<String> sMap = Stream.of("monkey", "gorilla", "bonobo");
33+
sMap.map(String::length).forEach(System.out::print); // 676
34+
35+
// faltMap()
36+
List<String> zero = Arrays.asList();
37+
List<String> one = Arrays.asList("Bonobo");
38+
List<String> two = Arrays.asList("Mama Gorilla", "Baby Gorilla");
39+
Stream<List<String>> animals = Stream.of(zero, one, two);
40+
animals.flatMap(l -> l.stream()).forEach(System.out::println);
41+
42+
// sorted()
43+
Stream<String> sSorted = Stream.of("brown-", "bear-");
44+
sSorted.sorted().forEach(System.out::print); // bear-brown-
45+
46+
Stream<String> sSorted2 = Stream.of("brown bear-", "grizzly-");
47+
sSorted2.sorted(Comparator.reverseOrder()).forEach(System.out::print); // grizzly-brow-bear-
48+
49+
// peek()
50+
Stream<String> stream = Stream.of("black bear", "brown bear", "grizzly");
51+
long count = stream.filter(st -> st.startsWith("g")).peek(System.out::println).count();
52+
System.out.println(count); // 1
53+
54+
List<String> list = Arrays.asList("Toby", "Anna", "Leroy", "Alex");
55+
list.stream()
56+
.filter(n -> n.length() == 4)
57+
.sorted()
58+
.limit(2)
59+
.forEach(System.out::println);
60+
61+
/**
62+
* 1. stream() sends Toby to filter() . filter() sees that the length is good and sends Toby to sorted()
63+
* . sorted() can’t sort yet because it needs all of the data, so it holds Toby.
64+
* 2. stream() sends Anna to filter() . filter() sees that the length is good and sends Anna to sorted()
65+
* . sorted() can’t sort yet because it needs all of the data, so it holds Anna.
66+
* 3. stream() sends Leroy to filter() . filter() sees that the length is not a match, and it takes Leroy out of the assembly line processing.
67+
* 4.stream() sends Alex to filter() . filter() sees that the length is good and sends Alex to sorted()
68+
* . sorted() can’t sort yet because it needs all of the data, so it holds Alex. It
69+
* turns out sorted() does have all of the required data, but it doesn’t know it yet.
70+
* 5. The foreman lets sorted() know that it is time to sort and the sort occurs.
71+
* 6. sorted() sends Alex to limit() . limit() remembers that it has seen one element and
72+
* sends Alex to forEach() , printing Alex .
73+
* 7. sorted() sends Anna to limit() . limit() remembers that it has seen two elements
74+
* and sends Anna to forEach() , printing Anna .
75+
* 8. limit() has now seen all of the elements that are needed and tells the foreman. The
76+
* foreman stops the line, and no more processing occurs in the pipeline.
77+
*/
78+
}
79+
80+
public static void main(String[] args) {
81+
StreamCommonIntermediateOprations s = new StreamCommonIntermediateOprations();
82+
s.test();
83+
}
84+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package functionalProgramming;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Optional;
6+
import java.util.Set;
7+
import java.util.TreeSet;
8+
import java.util.function.BinaryOperator;
9+
import java.util.function.Predicate;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.Stream;
12+
13+
/**
14+
*
15+
* @author chengfeili
16+
* Jun 8, 2017 9:44:45 PM
17+
*
18+
* You can perform a terminal operation without any intermediate
19+
* operations. Reductions are a special type of terminal operation where
20+
* all of the contents of the stream are combined into a single
21+
* primitive or Object.
22+
*
23+
*/
24+
public class StreamCommonTerminalOperations {
25+
26+
public void test() {
27+
// count()
28+
Stream<String> s = Stream.of("monkey", "gorilla", "bonobo");
29+
System.out.println(s.count()); // 3
30+
31+
// min() and max()
32+
Stream<String> sMin = Stream.of("monkey", "ape", "bonobo");
33+
Optional<String> min = sMin.min((s1, s2) -> s1.length() - s2.length());
34+
min.ifPresent(System.out::println); // ape
35+
36+
// findAny() and findFirst()
37+
Stream<String> sFind = Stream.of("monkey", "gorilla", "bonobo");
38+
Stream<String> infinite = Stream.generate(() -> "chimp");
39+
sFind.findAny().ifPresent(System.out::println); // monkey
40+
infinite.findAny().ifPresent(System.out::println); // chimp
41+
42+
// allMatch(), anyMatch() and nonMatch()
43+
List<String> list = Arrays.asList("monkey", "2", "chimp");
44+
Stream<String> infinite1 = Stream.generate(() -> "chimp");
45+
Predicate<String> pred = x -> Character.isLetter(x.charAt(0));
46+
System.out.println(list.stream().anyMatch(pred)); // true
47+
System.out.println(list.stream().allMatch(pred)); // false
48+
System.out.println(list.stream().noneMatch(pred)); // false
49+
System.out.println(infinite1.anyMatch(pred)); // true
50+
51+
// forEach()
52+
Stream<String> sForEach = Stream.of("Monkey", "Gorilla", "Bonobo");
53+
sForEach.forEach(System.out::print); // MonkeyGorillaBonobo
54+
55+
// reduce()
56+
// The most common ways of doing a reduction is to start with an initial
57+
// value and keep merging it with the next value
58+
Stream<String> stream = Stream.of("w", "o", "l", "f");
59+
String word = stream.reduce("", (ss, c) -> ss + c);
60+
System.out.println(word); // wolf
61+
62+
Stream<String> stream1 = Stream.of("w", "o", "l", "f");
63+
String word1 = stream1.reduce("", String::concat);
64+
System.out.println(word1);
65+
/*
66+
* In many cases, the identity isn’t really necessary, so Java lets
67+
* us omit it. When you don’t specify an identity, an Optional is
68+
* returned because there might not be any data. There are three choices
69+
* for what is in the Optional
70+
* ■ If the stream is empty, an empty Optional is returned.
71+
* ■ If the stream has one element, it is returned.
72+
* ■ If the stream has multiple elements, the accumulator is
73+
* applied to combine them.
74+
*/
75+
BinaryOperator<Integer> op = (a, b) -> a * b;
76+
Stream<Integer> empty = Stream.empty();
77+
Stream<Integer> oneElement = Stream.of(3);
78+
Stream<Integer> threeElements = Stream.of(3, 5, 6);
79+
empty.reduce(op).ifPresent(System.out::print); // no output
80+
oneElement.reduce(op).ifPresent(System.out::print); // 3
81+
threeElements.reduce(op).ifPresent(System.out::print); // 90
82+
83+
// collect()
84+
Stream<String> stream2 = Stream.of("w", "o", "l", "f");
85+
StringBuilder word2 = stream2.collect(StringBuilder::new,
86+
StringBuilder::append, StringBuilder::append);
87+
System.out.println(word2);
88+
89+
Stream<String> stream3 = Stream.of("w", "o", "l", "f");
90+
TreeSet<String> set3 = stream3.collect(Collectors.toCollection(TreeSet::new));
91+
System.out.println(set3); // [f, l, o, w]
92+
93+
// unsorted
94+
Stream<String> stream4 = Stream.of("w", "o", "l", "f");
95+
Set<String> set = stream4.collect(Collectors.toSet());
96+
System.out.println(set); // [f, w, l, o]
97+
}
98+
99+
public static void main(String[] args) {
100+
StreamCommonTerminalOperations s = new StreamCommonTerminalOperations();
101+
s.test();
102+
}
103+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package functionalProgramming;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.stream.Stream;
6+
7+
/**
8+
*
9+
* @author chengfeili
10+
* Jun 8, 2017 9:37:58 PM
11+
*
12+
*/
13+
public class StreamSources {
14+
15+
public void test() {
16+
Stream<String> empty = Stream.empty(); // count = 0;
17+
Stream<Integer> singleElement = Stream.of(1);
18+
Stream<Integer> formArray = Stream.of(1, 2, 3);
19+
// Java provides a convenient way to convert from a list to a stream
20+
List<String> list = new ArrayList<>();
21+
Stream<String> fromList = list.stream();
22+
Stream<String> fromListParallel = list.parallelStream();
23+
24+
// infinite stream
25+
Stream<Double> randoms = Stream.generate(Math::random);
26+
Stream<Integer> oddNumbers = Stream.iterate(1, n -> n + 2);
27+
}
28+
}

0 commit comments

Comments
 (0)