四.java8四大核心函數式接口
1.簡介
1.Comsumer
消費類型接口
void accept(T t)
直接消費類型
2.Supplier
供給型接口
T get();
直接獲取T類型
3.Function<T, R>
函數型接口
R apply(T t);
就是傳入一個t類型的參數然後應用到R類型
4.Predicate
斷言型接口
boolean test(T t)
傳日一個t類型的數據進行測試
還有一些子類,可以傳遞多個參數,具體見參考文檔。
2.代碼測試
public static void main(String[] args) {
FuorFunction function = new FuorFunction();
function.test4();
}
public void test() {
getNumList(10, () -> (int)(Math.random() * 100)).forEach(System.out::println);
}
//測試Supplier函數接口
public List<Integer> getNumList(int num, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<>();
for(int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
//測試Function接口
public void test2() {
String s = "fdad, FDADS";
strHander(s, (x) ->x.substring(0,5));
}
public void strHander(String s, Function<String, String>fun) {
System.out.println(fun.apply(s));
}
//測試Costumer接口
public void test3() {
testCuns(10000.0, (x) -> System.out.println("這次消費爲:" + x + "元"));
}
public void testCuns(double money,Consumer<Double>con) {
con.accept(money);
}
//將滿足條件的字符串,放入集合中
public List<String> filterStr(List<String> ss, Predicate<String>pre) {
List<String> strlist = new ArrayList<>();
for(String str : ss) {
System.out.println(str.length());
if(pre.test(str)) {
strlist.add(str);
}
}
return strlist;
}
public void test4() {
String []ss = {"中國", "必反" , "中大", "fdae"};
List<String>t = Arrays.asList(ss);
List<String>list = filterStr(t, (s) -> s.length() > 3);
for(String tmp : list) {
System.out.println(tmp);
}
}
五.方法引用
(1)對象::實例方法名字
(2)類::靜態方法名字
(3)類::實例方法名字
3.注意事項:
(1)lambda體中的參數列表與返回類型,與函數式接口中抽象方法的函數列表和返回類型值保持一致
(2)若參數列表中第一參數是實例方法的調用者,第二參數是實例方法的參數時,可以ClassName::method;
(3)需要調用構造器的參數列表要與函數式接口中抽象方法的參數列表保持一致。
4.
//類::實例方法名字
public void test4(){
BiPredicate<String, String>bp(x, y) -> x.equal(y);
//第一個參數是實例方法的調用者,第二個參數是調用方法的參數
BiPredicate<String, String>bom = String :: equal();
}
六.中間操作
1.中間操作的特點:
沒有終止操作,中間操作不會執行,這就是惰性求值。
2.分類
(1)篩選與切片
常用的方法有
-
- filter(斷言型接口 Predicate)
- 根據接口函數的實現進行過濾
-
- limit (n)
- 相當於數據庫中的limit,選中前n個
-
- skip (n)
- 相當於數據庫中的skip,跳過前n個
-
- distinct
- 去重
(2)映射
-
- map (函數式接口 Function)
- 相當於數據庫中的select name ,具體的將某一屬性提取出來
-
- flatmap(函數式接口 Function)
- 相當於集合的並集操作,將集合中的集合變得扁平。
(3)排序
-
- sorted()
- 自然排序,按照comparable 按照系統默認
- 定製排序 comparator ,自己實現的比較器排序
示例:
先用Employee實現Comparable接口
//使用年齡進行默認排序
@Override
public int compareTo(Object o) {
if(this.age > ((Employee)o).getAge())return 1;
else if(this.age < ((Employee) o).getAge())return -1;
else return 0;
}
public void test2(){
//需求:獲取當前工四年齡大於32的員工信息
List<Employee>empoyees = Arrays.asList(
new Employee(14, "張三"),
new Employee(37, "李四"),
new Employee(36, "王五"),
new Employee(35, "趙劉")
);
//篩選與切片
//內部迭代,是sreamAPI完成的
//中間操作:不執行任何操作,也就是沒有終止操作,過濾不會執行
Stream<Employee> stream = empoyees.stream()
.filter((e) -> e.getAge() > 35);
//終止操作,一次執行全部內容:這就是"惰性求值"
stream.forEach(System.out::println);
//可以短路,一旦發現n條滿足的就停止。
System.out.println("大於5000的");
empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.limit(2)
.forEach(System.out::println);
//跳過和去重(重寫hashcode和equals)
System.out.println("大於5000的跳過前兩個");
empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.skip(2)
.distinct()
.forEach(System.out::println);
//排序
//定製排序
System.out.println("定製排序");
empoyees.stream()
.sorted((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
.forEach(System.out::println);
//自然排序
System.out.println("自然排序");
empoyees.stream()
.sorted()
.forEach(System.out::println);
}
七.終止操作
1.特點:一般是consumer接口的調用函數
比如foreach;
2.類型
(1)查找與匹配
- allMatch
- noneMatch
- anyMatch
- findFirst
- count
- max
- min
- findAny
前三個返回的boolean,後邊返回Optional
如果找到的值是有可能是空的就返回Optional。
(3)歸約與收集
-
- reduce(identity(初值),accumlator(歸約器))
- 將流中的所有元素反覆結合起來
- map-reduce廣泛應用於數據搜索
-
- collect (Collectors.)
- Collectors方便創建常見的收集器實例包括
-
數字操作
- 最大值
- 最小值
- 求和
- 平均值 Collection.avarangeDouble(函數式接口);
- 總數字 Collectors.counting()
-
分組
- Collectors.groupingBy(函數式接口) 返回值是一個Map, map沒有stream - partitioningBy
-
分區
插入一個遍歷map的方法
for(Map<String, String>entry : map.entrySet{
entry.getKey();
entry.getValue();
}
難一點,慢一點的
for (String key : map.keySet){
key + map.get(key);
}
示例
List<Employee> empoyees = Arrays.asList(
new Employee(14, "張三", Employee.Status.FREE),
new Employee(37, "李四",Employee.Status.FREE),
new Employee(36, "王五",Employee.Status.VOCATION),
new Employee(35, "趙劉",Employee.Status.BUSY)
);
boolean b1 = empoyees.stream()
.allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
System.out.println(empoyees.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)));
System.out.println(empoyees.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)));
Optional<Employee> op = empoyees.stream()
.sorted((e1,e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
.findFirst();
Optional<Employee> op2 = empoyees.stream()
.filter((e) -> e.getStatus().equals(Employee.Status.FREE))
.findAny();
Optional<Employee> op3 = empoyees.parallelStream()
.filter((e) -> e.getStatus().equals(Employee.Status.FREE))
.findAny();
System.out.println(op.get());
System.out.println(op2.get());
System.out.println(op3.get());
long count = empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.count();
System.out.println(count);
Optional<Employee> op5 = empoyees.stream()
.max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op5.get());
//使用映射提取屬性
Optional<Integer> op6 = empoyees.stream()
.map(Employee::getSalary)
.min(Integer::compare);
System.out.println(op6.get());
//reduce歸
Integer []nums = {1, 3, 5};
List<Integer> list = Arrays.asList(nums);
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(sum);
Optional<Integer> opt1 = empoyees.stream()
.map(Employee::getSalary)
.reduce(Integer::sum);
System.out.println(opt1.get());
/*
*
* collect收集,將流轉換成其他形式,接受一個Collector 接口實現,給stream芳芳
* */
List<String> list2 = empoyees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list2.forEach(System.out::println);
Set<String> set = empoyees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
set.forEach(System.out::println);
Long count3 = empoyees.stream()
.collect(Collectors.counting());
Double ave = empoyees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(count3);
System.out.println(ave);
Double sum2 = empoyees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
//最大值
Optional<Integer>max = empoyees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1, e2)));
System.out.println(max.get());
//最小值的人
Optional<Employee>min = empoyees.stream()
.collect(Collectors.minBy((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary())));
//怎麼只收集名字和狀態而不收集list
Map<Employee.Status,List<Employee>>map = empoyees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
map.entrySet().forEach((x) -> System.out.println(x.getKey() + " :" + x.getValue()));
//多級分組
Map<Employee.Status, Map<String,List<Employee>>>mas = empoyees.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if(((Employee)e).getAge() <= 35) {
return "青年";
}else if(((Employee)e).getAge() <= 50){
return "中年";
}else {
return "老年";
}
})));
System.out.println(mas);
//分區
Map<Boolean, List<Employee>>ex = empoyees.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
System.out.println(ex);
/*
*
*
* */
Optional<Integer> count2 = empoyees.stream()
.map((e) -> 1) //每一個人返回一個1然後計算
.reduce(Integer::sum);
System.out.println(count2.get());