import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.function.*;
import java.util.stream.*;
import static java.util.stream.Collectors.*;

class LambdaTest {
    public static void main(String[] args) {
        List<Emp> list = new ArrayList<>();

        Dept dept1 = new Dept(1);
        Dept dept2 = new Dept(2);
        Dept dept3 = new Dept(3);

        list.add(new Emp(dept1, 500));
        list.add(new Emp(dept1, 1000));
        list.add(new Emp(dept1, 1500));
        list.add(new Emp(dept1, 2000));

        list.add(new Emp(dept2, 1500));
        list.add(new Emp(dept2, 2000));
        list.add(new Emp(dept2, 2500));
        list.add(new Emp(dept2, 3000));

        list.add(new Emp(dept3, 0));
        list.add(new Emp(dept3, 100));
        list.add(new Emp(dept3, 200));
        list.add(new Emp(dept3, 500));

        new LambdaTest().rankedBySalAndFilter(list);
    }
    
    
    public static <T, A, R> Collector<T, ?, R> filtering(Predicate<? super T> predicate, Collector<? super T, A, R> collector) {
        BiConsumer<A, ? super T> downstream = collector.accumulator();
        return Collector.<T, A, R>of(collector.supplier(),
                (a, t) -> {if (predicate.test(t)) downstream.accept(a, t);},
                collector.combiner(), collector.finisher(),
                collector.characteristics().stream().toArray(Collector.Characteristics[]::new));
    }

    void rankedBySalAndFilter(List<Emp> list) {
        Map<Dept, Long> map = list.stream()
        	.filter(emp -> emp.sal > 1000)
            .collect(groupingBy(emp -> emp.dept, counting()));

        System.out.println(map);
    }

    static class Emp {
        Emp(Dept dept, Integer sal) {
            this.dept = dept;
            this.sal = sal;
        }

        Integer empno;
        Dept dept;
        String ename;
        String job;
        Integer mgr;
        Date hiredate;
        Integer sal;
        Integer comm;
    }

    static class Dept {
        Dept(Integer deptno) {
            this.deptno = deptno;
        }

        Integer deptno;
        String dname;
        String loc;

        @Override
        public String toString() {
            return "deptno" + deptno;
        }
    }
}
