1. 程式人生 > 實用技巧 >java lambda & stream api

java lambda & stream api

Lambda


Scenario 1

@Test
    public void testLambda1(){
        new Thread(()->{
            System.out.println("Hello? Is Frank in?");
        }).start();
        new Thread(()->{
            System.out.println("Yeah?");
        }).start();
}

Scenario 2


@Test
public void testConsumer(){
// Before Use Lambda
Consumer con1 = new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con1.accept("Love");

    // After Use Lambda
    Consumer<String> con2 = (s) ->{
        System.out.println(s);
    };
    con2.accept("Family");

}

Scenario 3

Actually I used in scenario 2

Scenario 4

 Consumer<String> con3 = s -> System.out.println(s);
        con3.accept("Phoenix");

Scenario 5


@Test
public void testComparator(){
// Before Lambda Expression
Comparator com1 = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};

    // After Use Lambda Expression
    Comparator<Integer> com2 = (o1, o2) ->{
        return o1.compareTo(o2);
    };
}

Scenario 6


I used it in Scenario 4

The Big Four Functional Interfaces


Consumer

@Test
    public void testFunctional1(){
        // Before Lambda
        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("I have " + aDouble + " dollars.");
            }
        });

        // After Lambda
        happyTime(600, money-> System.out.println("I have " + money + " dollars."));
    }

    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }

Predicate

@Test
    public void testPredicate(){
        List<String> listOld = new ArrayList<>();
        List<String> listNew = new ArrayList<>();
        listOld.add("Love");
        listOld.add("Tom");
        listOld.add("Truman");
        listOld.add("Villanelle");
        listOld.add("JackUltraman");
        
        // Before Lambda
        listNew = filterString(listOld, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                if(s.length() > 5){
                    return true;
                }else{
                    return false;
                }
            }
        });
//        Iterator<String> iterator = listNew.iterator();
//        if(iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
        for(String s : listNew){
            System.out.println(s);
        }

        // After Lambda
        List<String> listNew2 = new ArrayList<>();
        listNew2 = filterString(listOld, s -> {
            if(s.length() > 5) return true;
            else return false;
        });
        for(String s : listNew2){
            System.out.println(s);
        }
    }

    public List<String> filterString(List<String> list, Predicate<String> pre){
        List<String> filterList = new ArrayList<>();
        for(String s : list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }
        return filterList;
    }

Method References

@Test
    public void testMethodReference(){
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("Phoenix City");

        System.out.println("*****************************************");
        Consumer<String> con2 = System.out::println;
        con2.accept("Chicago");
    }

Stream


get a stream

public class StreamTest {
    List<Employee> employees = new ArrayList<>();

    @Test
    public void test1(){
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1002, "Jerry", 24, 189.80));
        employees.add(new Employee(1003, "Kate", 22, 289.80));
        employees.add(new Employee(1004, "Lucy", 25, 389.80));
        employees.add(new Employee(1005, "McEncy", 27, 489.80));
        employees.add(new Employee(1006, "Red", 28, 589.80));
        employees.add(new Employee(1007, "Jack", 29, 689.80));
        employees.add(new Employee(1008, "Robert", 33, 989.80));

        Stream<Employee> stream = employees.stream();
}

int[] arr = {1, 2, 3, 4};
        IntStream stream1 = Arrays.stream(arr);



  Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);

The Operation of Stream API

@Test
    public void testStream1(){
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1002, "Jerry", 24, 189.80));
        employees.add(new Employee(1003, "Kate", 22, 289.80));
        employees.add(new Employee(1004, "Lucy", 25, 389.80));
        employees.add(new Employee(1005, "McEncy", 27, 489.80));
        employees.add(new Employee(1006, "Red", 28, 589.80));
        employees.add(new Employee(1007, "Jack", 29, 689.80));
        employees.add(new Employee(1008, "Robert", 33, 989.80));

        employees.stream().filter(e->e.getSalary() > 600).forEach(System.out::println); // here, foreach() is important, otherwise the filter() won't work
        // the output is : 
        // Employee{id=1001, name='Tom', age=23, salary=789.8}
        // Employee{id=1007, name='Jack', age=29, salary=689.8}
        // Employee{id=1008, name='Robert', age=33, salary=989.8}

        // limit()
        employees.stream().limit(3).forEach(System.out::println);
        // the output is the first 3 line of the list
    }
  @Test
    public void testStream2(){
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.stream()
                .distinct()
                .forEach(System.out::println);
        // the output is only one line:
        // Employee{id=1001, name='Tom', age=23, salary=789.8}

    }

@Test
    public void testStreamMap(){
        List<String> list = new ArrayList<>();
        list.add("make");
        list.add("friends");
        list.add("with");
        list.add("you");
        list.stream()
                .map(str -> str.toUpperCase())
                .forEach(System.out::println); // MAKE FRIENDS WITH YOU
    }

if there is an object, then first map(), then filter()

flatmap() to map() is just like addAll() to add()
that means map() can return a stream which has many steams in it, while flatmap() will only return you a stream


sorted

 @Test
    public void testSort1(){
        // 自然排序
        List<Integer> list = Arrays.asList(45, 32, 78, 9, 23, 88);
        list.stream()
                .sorted()
                .forEach(System.out::println);
        // 定製排序
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1002, "Jerry", 24, 189.80));
        employees.add(new Employee(1003, "Kate", 22, 289.80));
        employees.add(new Employee(1004, "Lucy", 25, 389.80));
        employees.add(new Employee(1005, "McEncy", 27, 489.80));
        employees.add(new Employee(1006, "Red", 28, 589.80));
        employees.add(new Employee(1007, "Jack", 29, 689.80));
        employees.add(new Employee(1008, "Robert", 33, 989.80));

        employees.stream()
                .sorted((e1, e2)->{ // here you use Comparator interface
                    return Integer.compare(e1.getAge(), e2.getAge());
                })
                .forEach(System.out::println);


    }

終止操作


@Test
    public void testTerminate(){
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1002, "Jerry", 24, 189.80));
        employees.add(new Employee(1003, "Kate", 22, 289.80));
        employees.add(new Employee(1004, "Lucy", 25, 389.80));
        employees.add(new Employee(1005, "McEncy", 27, 489.80));
        employees.add(new Employee(1006, "Red", 28, 589.80));
        employees.add(new Employee(1007, "Jack", 29, 689.80));
        employees.add(new Employee(1008, "Robert", 33, 989.80));

        // allMatch(Predicate pre)
        boolean b = employees.stream()
                .allMatch(e -> e.getAge() > 18);
        System.out.println(b); // true

        // anyMatch(Predicate pre)
        boolean b1 = employees.stream()
                .anyMatch(e -> e.getSalary() > 700);
        System.out.println(b1);  // true

        // noneMatch(Predicate pre)
        // 是否沒有員工超過60歲
        boolean b2 = employees.stream()
                .noneMatch(e1 -> e1.getAge() > 60);
        System.out.println(b2); // true :


        // findFirst() : 返回第一個元素
        Optional<Employee> employee = employees.stream()
                .findFirst();
        System.out.println(employee); //  Optional[Employee{id=1001, name='Tom', age=23, salary=789.8}]

        // findAny()
        Optional<Employee> employee1 = employees.parallelStream()  // findAny() in stream always find the first one
                .findAny();                                          // but when you use parallel stream, things gonna be different
        System.out.println(employee1);

        // count()
        long count = employees.stream()
                .filter(e1 -> e1.getSalary() > 600)
                .count();
        System.out.println(count); // 3

        // max(Comparator c)
        Optional<Double> max = employees.stream()
                .map(Employee::getSalary)
                .max((x, y) -> Double.compare(x, y));
        System.out.println(max);  // Optional[989.8]
    }

Reduce

 @Test
    public void testReduce(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer reduce = list.stream()
                .reduce(0, Integer::sum);
        System.out.println(reduce); // 55
    }

 // the sum of all salary 
        Double reduce = employees.stream()
                .map(Employee::getSalary)
                .reduce(0.0, Double::sum);
        System.out.println(reduce); // 4418.400000000001

Collect

@Test
    public void testCollect(){
        employees.add(new Employee(1001, "Tom", 23, 789.80));
        employees.add(new Employee(1002, "Jerry", 24, 189.80));
        employees.add(new Employee(1003, "Kate", 22, 289.80));
        employees.add(new Employee(1004, "Lucy", 25, 389.80));
        employees.add(new Employee(1005, "McEncy", 27, 489.80));
        employees.add(new Employee(1006, "Red", 28, 589.80));
        employees.add(new Employee(1007, "Jack", 29, 689.80));
        employees.add(new Employee(1008, "Robert", 33, 989.80));

        List<Employee> list = employees.stream()
                .filter(e -> e.getSalary() > 600)
                .collect(Collectors.toList());
       for(Employee e1 : list){
           System.out.println(e1.getName()); // Tom  Jack  Robert
       }
    }