初識Lambda-含API及Demo

/*
 * 一、Lambda 表達式的基礎語法:Java8中引入了一個新的操作符 "->" 該操作符稱爲箭頭操作符或 Lambda 操作符
 *   箭頭操作符將 Lambda 表達式拆分成兩部分:
 * 
 * 左側:Lambda 表達式的參數列表
 * 右側:Lambda 表達式中所需執行的功能, 即 Lambda 體
 * 
 * 語法格式一:無參數,無返回值
 *         () -> System.out.println("Hello Lambda!");
 * 
 * 語法格式二:有一個參數,並且無返回值
 *         (x) -> System.out.println(x)
 * 
 * 語法格式三:若只有一個參數,小括號可以省略不寫
 *         x -> System.out.println(x)
 * 
 * 語法格式四:有兩個以上的參數,有返回值,並且 Lambda 體中有多條語句
 *        Comparator<Integer> com = (x, y) -> {
 *            System.out.println("函數式接口");
 *            return Integer.compare(x, y);
 *        };
 *
 * 語法格式五:若 Lambda 體中只有一條語句, return 和 大括號都可以省略不寫
 *         Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
 * 
 * 語法格式六:Lambda 表達式的參數列表的數據類型可以省略不寫,因爲JVM編譯器通過上下文推斷出,數據類型,即“類型推斷”
 *         (Integer x, Integer y) -> Integer.compare(x, y);
 * 
 * 上聯:左右遇一括號省
 * 下聯:左側推斷類型省
 * 橫批:能省則省
 * 
 * 二、Lambda 表達式需要“函數式接口”的支持
 * 函數式接口:接口中只有一個抽象方法的接口,稱爲函數式接口。 可以使用註解 @FunctionalInterface 修飾
 *              可以檢查是否是函數式接口
 */ 

package com.atguigu.java8;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import org.junit.Test;


public class TestLambda2 {
	
	@Test
	public void test1(){
		int num = 0;//jdk 1.7 前,必須是 final
		
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello World!" + num);
			}
		};
		
		r.run();
		
		System.out.println("-------------------------------");
		
		Runnable r1 = () -> System.out.println("Hello Lambda!");
		r1.run();
	}
	
	@Test
	public void test2(){
		Consumer<String> con = x -> System.out.println(x);
		con.accept("威武!");
	}
	
	@Test
	public void test3(){
		Comparator<Integer> com = (x, y) -> {
			System.out.println("函數式接口");
			return Integer.compare(x, y);
		};
	}
	
	@Test
	public void test4(){
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
	}
	
	@Test
	public void test5(){
//		String[] strs;
//		strs = {"aaa", "bbb", "ccc"};
		
		List<String> list = new ArrayList<>();
		
		show(new HashMap<>());
	}

	public void show(Map<String, Integer> map){
		
	}
	
	//需求:對一個數進行運算
	@Test
	public void test6(){
		Integer num = operation(100, (x) -> x * x);
		System.out.println(num);
		
		System.out.println(operation(200, (y) -> y + 200));
	}
	
	public Integer operation(Integer num, MyFun mf){
		return mf.getValue(num);
	}
}

/*
 * Java8 內置的四大核心函數式接口
 * 
 * Consumer<T> : 消費型接口
 *         void accept(T t);
 * 
 * Supplier<T> : 供給型接口
 *         T get(); 
 * 
 * Function<T, R> : 函數型接口
 *         R apply(T t);
 * 
 * Predicate<T> : 斷言型接口
 *         boolean test(T t);
 * 
 */ 

package com.atguigu.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.junit.Test;


public class TestLambda3 {
	
	//Predicate<T> 斷言型接口:
	@Test
	public void test4(){
		List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
		List<String> strList = filterStr(list, (s) -> s.length() > 3);
		
		for (String str : strList) {
			System.out.println(str);
		}
	}
	
	//需求:將滿足條件的字符串,放入集合中
	public List<String> filterStr(List<String> list, Predicate<String> pre){
		List<String> strList = new ArrayList<>();
		
		for (String str : list) {
			if(pre.test(str)){
				strList.add(str);
			}
		}
		
		return strList;
	}
	
	//Function<T, R> 函數型接口:
	@Test
	public void test3(){
		String newStr = strHandler("\t\t\t 威武   ", (str) -> str.trim());
		System.out.println(newStr);
		
		String subStr = strHandler("威武", (str) -> str.substring(2, 5));
		System.out.println(subStr);
	}
	
	//需求:用於處理字符串
	public String strHandler(String str, Function<String, String> fun){
		return fun.apply(str);
	}
	
	//Supplier<T> 供給型接口 :
	@Test
	public void test2(){
		List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
		
		for (Integer num : numList) {
			System.out.println(num);
		}
	}
	
	//需求:產生指定個數的整數,並放入集合中
	public List<Integer> getNumList(int num, Supplier<Integer> sup){
		List<Integer> list = new ArrayList<>();
		
		for (int i = 0; i < num; i++) {
			Integer n = sup.get();
			list.add(n);
		}
		
		return list;
	}
	
	//Consumer<T> 消費型接口 :
	@Test
	public void test1(){
		happy(10000, (m) -> System.out.println("你們剛哥喜歡大寶劍,每次消費:" + m + "元"));
	} 
	
	public void happy(double money, Consumer<Double> con){
		con.accept(money);
	}
}

/*
 * 一、方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可以使用方法引用
 *               (可以將方法引用理解爲 Lambda 表達式的另外一種表現形式)
 * 
 * 1. 對象的引用 :: 實例方法名
 * 
 * 2. 類名 :: 靜態方法名
 * 
 * 3. 類名 :: 實例方法名
 * 
 * 注意:
 *      ①方法引用所引用的方法的參數列表與返回值類型,需要與函數式接口中抽象方法的參數列表和返回值類型保持一致!
 *      ②若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式: ClassName::MethodName
 * 
 * 二、構造器引用 :構造器的參數列表,需要與函數式接口中參數列表保持一致!
 * 
 * 1. 類名 :: new
 * 
 * 三、數組引用
 * 
 *     類型[] :: new;
 * 
 * 
 */

public class TestMethodRef {
	//數組引用
	@Test
	public void test8(){
		Function<Integer, String[]> fun = (args) -> new String[args];
		String[] strs = fun.apply(10);
		System.out.println(strs.length);
		
		System.out.println("--------------------------");
		
		Function<Integer, Employee[]> fun2 = Employee[] :: new;
		Employee[] emps = fun2.apply(20);
		System.out.println(emps.length);
	}
	
	//構造器引用
	@Test
	public void test7(){
		Function<String, Employee> fun = Employee::new;
		
		BiFunction<String, Integer, Employee> fun2 = Employee::new;
	}
	
	@Test
	public void test6(){
		Supplier<Employee> sup = () -> new Employee();
		System.out.println(sup.get());
		
		System.out.println("------------------------------------");
		
		Supplier<Employee> sup2 = Employee::new;
		System.out.println(sup2.get());
	}
	
	//類名 :: 實例方法名
	@Test
	public void test5(){
		BiPredicate<String, String> bp = (x, y) -> x.equals(y);
		System.out.println(bp.test("abcde", "abcde"));
		
		System.out.println("-----------------------------------------");
		
		BiPredicate<String, String> bp2 = String::equals;
		System.out.println(bp2.test("abc", "abc"));
		
		System.out.println("-----------------------------------------");
		
		
		Function<Employee, String> fun = (e) -> e.show();
		System.out.println(fun.apply(new Employee()));
		
		System.out.println("-----------------------------------------");
		
		Function<Employee, String> fun2 = Employee::show;
		System.out.println(fun2.apply(new Employee()));
		
	}
	
	//類名 :: 靜態方法名
	@Test
	public void test4(){
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
		
		System.out.println("-------------------------------------");
		
		Comparator<Integer> com2 = Integer::compare;
	}
	
	@Test
	public void test3(){
		BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
		System.out.println(fun.apply(1.5, 22.2));
		
		System.out.println("--------------------------------------------------");
		
		BiFunction<Double, Double, Double> fun2 = Math::max;
		System.out.println(fun2.apply(1.2, 1.5));
	}

	//對象的引用 :: 實例方法名
	@Test
	public void test2(){
		Employee emp = new Employee(101, "張三", 18, 9999.99);
		
		Supplier<String> sup = () -> emp.getName();
		System.out.println(sup.get());
		
		System.out.println("----------------------------------");
		
		Supplier<String> sup2 = emp::getName;
		System.out.println(sup2.get());
	}
	
	@Test
	public void test1(){
		PrintStream ps = System.out;
		Consumer<String> con = (str) -> ps.println(str);
		con.accept("Hello World!");
		
		System.out.println("--------------------------------");
		
		Consumer<String> con2 = ps::println;
		con2.accept("Hello Java8!");
		
		Consumer<String> con3 = System.out::println;
	}
	
}

/*
 * 一、Stream API 的操作步驟:
 * 
 * 1. 創建 Stream
 * 
 * 2. 中間操作
 * 
 * 3. 終止操作(終端操作)
 */

public class TestStreamaAPI {
	
	//1. 創建 Stream
	@Test
	public void test1(){
		//1. Collection 提供了兩個方法  stream() 與 parallelStream()
		List<String> list = new ArrayList<>();
		Stream<String> stream = list.stream(); //獲取一個順序流
		Stream<String> parallelStream = list.parallelStream(); //獲取一個並行流
		
		//2. 通過 Arrays 中的 stream() 獲取一個數組流
		Integer[] nums = new Integer[10];
		Stream<Integer> stream1 = Arrays.stream(nums);
		
		//3. 通過 Stream 類中靜態方法 of()
		Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
		
		//4. 創建無限流
		//迭代
		Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
		stream3.forEach(System.out::println);
		
		//生成
		Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
		stream4.forEach(System.out::println);
		
	}
	
	//2. 中間操作
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66),
			new Employee(101, "張三", 18, 9999.99),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);
	
	/*
	  篩選與切片
		filter——接收 Lambda , 從流中排除某些元素。
		limit——截斷流,使其元素不超過給定數量。
		skip(n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
		distinct——篩選,通過流所生成元素的 hashCode() 和 equals() 去除重複元素
	 */
	
	//內部迭代:迭代操作 Stream API 內部完成
	@Test
	public void test2(){
		//所有的中間操作不會做任何的處理
		Stream<Employee> stream = emps.stream()
			.filter((e) -> {
				System.out.println("測試中間操作");
				return e.getAge() <= 35;
			});
		
		//只有當做終止操作時,所有的中間操作會一次性的全部執行,稱爲“惰性求值”
		stream.forEach(System.out::println);
	}
	
	//外部迭代
	@Test
	public void test3(){
		Iterator<Employee> it = emps.iterator();
		
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	@Test
	public void test4(){
		emps.stream()
			.filter((e) -> {
				System.out.println("短路!"); // &&  ||
				return e.getSalary() >= 5000;
			}).limit(3)
			.forEach(System.out::println);
	}
	
	@Test
	public void test5(){
		emps.parallelStream()
			.filter((e) -> e.getSalary() >= 5000)
			.skip(2)
			.forEach(System.out::println);
	}
	
	@Test
	public void test6(){
		emps.stream()
			.distinct()
			.forEach(System.out::println);
	}
}

 

public class TestStreamAPI1 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66),
			new Employee(101, "張三", 18, 9999.99),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);
	
	//2. 中間操作
	/*
		映射
		map——接收 Lambda , 將元素轉換成其他形式或提取信息。接收一個函數作爲參數,該函數會被應            
        用到每個元素上,並將其映射成一個新的元素。
		flatMap——接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流
	 */
	@Test
	public void test1(){
		Stream<String> str = emps.stream()
			.map((e) -> e.getName());
		
		System.out.println("-------------------------------------------");
		
		List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
		
		Stream<String> stream = strList.stream()
			   .map(String::toUpperCase);
		
		stream.forEach(System.out::println);
		
		Stream<Stream<Character>> stream2 = strList.stream()
			   .map(TestStreamAPI1::filterCharacter);
		
		stream2.forEach((sm) -> {
			sm.forEach(System.out::println);
		});
		
		System.out.println("---------------------------------------------");
		
		Stream<Character> stream3 = strList.stream()
			   .flatMap(TestStreamAPI1::filterCharacter);
		
		stream3.forEach(System.out::println);
	}

	public static Stream<Character> filterCharacter(String str){
		List<Character> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch);
		}
		
		return list.stream();
	}

    // 通過map進行遍歷,取集合裏面的元素到另外一個集合中
    public static void mapForeach(){

         list<Persion>.stream().map(item-> {
                Persion p= new Persion();
                p.setId(item.getId);
                p.setName(item.getName)
            }).collect(Collectors.toList());

	}


	/*
		sorted()——自然排序
		sorted(Comparator com)——定製排序
	 */
	@Test
	public void test2(){
		emps.stream()
			.map(Employee::getName)
			.sorted()
			.forEach(System.out::println);
		
		System.out.println("------------------------------------");
		
		emps.stream()
			.sorted((x, y) -> {
				if(x.getAge() == y.getAge()){
					return x.getName().compareTo(y.getName());
				}else{
					return Integer.compare(x.getAge(), y.getAge());
				}
			}).forEach(System.out::println);
	}
}
public class TestStreamAPI2 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Status.BUSY),
			new Employee(101, "張三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	
	//3. 終止操作
	/*
		allMatch——檢查是否匹配所有元素
		anyMatch——檢查是否至少匹配一個元素
		noneMatch——檢查是否沒有匹配的元素
		findFirst——返回第一個元素
		findAny——返回當前流中的任意元素
		count——返回流中元素的總個數
		max——返回流中最大值
		min——返回流中最小值
	 */
	@Test
	public void test1(){
			boolean bl = emps.stream()
				.allMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl);
			
			boolean bl1 = emps.stream()
				.anyMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl1);
			
			boolean bl2 = emps.stream()
				.noneMatch((e) -> e.getStatus().equals(Status.BUSY));
			
			System.out.println(bl2);
	}
	
	@Test
	public void test2(){
		Optional<Employee> op = emps.stream()
			.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
			.findFirst();
		
		System.out.println(op.get());
		
		System.out.println("--------------------------------");
		
		Optional<Employee> op2 = emps.parallelStream()
			.filter((e) -> e.getStatus().equals(Status.FREE))
			.findAny();
		
		System.out.println(op2.get());
	}
	
	@Test
	public void test3(){
		long count = emps.stream()
						 .filter((e) -> e.getStatus().equals(Status.FREE))
						 .count();
		
		System.out.println(count);
		
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.max(Double::compare);
		
		System.out.println(op.get());
		
		Optional<Employee> op2 = emps.stream()
			.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		
		System.out.println(op2.get());
	}
	
	//注意:流進行了終止操作後,不能再次使用
	@Test
	public void test4(){
		Stream<Employee> stream = emps.stream()
		 .filter((e) -> e.getStatus().equals(Status.FREE));
		
		long count = stream.count();
		
		stream.map(Employee::getSalary)
			.max(Double::compare);
	}
}
public class TestStreamAPI3 {
	
	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 79, 6666.66, Status.BUSY),
			new Employee(101, "張三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	
	//3. 終止操作
	/*
		歸約
		reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以將流中元素反覆結合起來,得到一個值。
	 */
	@Test
	public void test1(){
		List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		
		Integer sum = list.stream()
			.reduce(0, (x, y) -> x + y);
		
		System.out.println(sum);
		
		System.out.println("----------------------------------------");
		
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.reduce(Double::sum);
		
		System.out.println(op.get());
	}
	
	//需求:搜索名字中 “六” 出現的次數
	@Test
	public void test2(){
		Optional<Integer> sum = emps.stream()
			.map(Employee::getName)
			.flatMap(TestStreamAPI1::filterCharacter)
			.map((ch) -> {
				if(ch.equals('六'))
					return 1;
				else 
					return 0;
			}).reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
	
	//collect——將流轉換爲其他形式。接收一個 Collector接口的實現,用於給Stream中元素做彙總的方法
	@Test
	public void test3(){
		List<String> list = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toList());
		
		list.forEach(System.out::println);
		
		System.out.println("----------------------------------");
		
		Set<String> set = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toSet());
		
		set.forEach(System.out::println);

		System.out.println("----------------------------------");
		
		HashSet<String> hs = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.toCollection(HashSet::new));
		
		hs.forEach(System.out::println);
	}
	
	@Test
	public void test4(){
		Optional<Double> max = emps.stream()
			.map(Employee::getSalary)
			.collect(Collectors.maxBy(Double::compare));
		
		System.out.println(max.get());
		
		Optional<Employee> op = emps.stream()
			.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
		
		System.out.println(op.get());
		
		Double sum = emps.stream()
			.collect(Collectors.summingDouble(Employee::getSalary));
		
		System.out.println(sum);
		
		Double avg = emps.stream()
			.collect(Collectors.averagingDouble(Employee::getSalary));
		
		System.out.println(avg);
		
		Long count = emps.stream()
			.collect(Collectors.counting());
		
		System.out.println(count);
		
		System.out.println("--------------------------------------------");
		
		DoubleSummaryStatistics dss = emps.stream()
			.collect(Collectors.summarizingDouble(Employee::getSalary));
		
		System.out.println(dss.getMax());
	}
	
	//分組
	@Test
	public void test5(){
		Map<Status, List<Employee>> map = emps.stream()
			.collect(Collectors.groupingBy(Employee::getStatus));
		
		System.out.println(map);
	}
	
	//多級分組
	@Test
	public void test6(){
		Map<Status, Map<String, List<Employee>>> map = emps.stream()
			.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
				if(e.getAge() >= 60)
					return "老年";
				else if(e.getAge() >= 35)
					return "中年";
				else
					return "成年";
			})));
		
		System.out.println(map);
	}
	
	//分區
	@Test
	public void test7(){
		Map<Boolean, List<Employee>> map = emps.stream()
			.collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
		
		System.out.println(map);
	}
	
	//
	@Test
	public void test8(){
		String str = emps.stream()
			.map(Employee::getName)
			.collect(Collectors.joining("," , "----", "----"));
		
		System.out.println(str);
	}
	
	@Test
	public void test9(){
		Optional<Double> sum = emps.stream()
			.map(Employee::getSalary)
			.collect(Collectors.reducing(Double::sum));
		
		System.out.println(sum.get());
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章