Java8 新特性

特性

  • 速度更快
  • 代碼更少(增長了新的語法Lambda 表達式)
  • 強大的Stream API便於並行
  • 最大化減小空指針異常Optional
  • 其中最爲核心的爲Lambda 表達式與Stream API

Lambda表達式

Lambda 是一個匿名函數,咱們能夠把Lambda表達式理解爲是一段能夠傳遞的代碼(將代碼像數據同樣進行傳遞)。能夠寫出更簡潔、更靈活的代碼。做爲一種更緊湊的代碼風格,使Java的語言表達能力獲得了提高。java

public class TestLambda1 {
	
	//原來的匿名內部類
	@Test
	public void test1(){
		Comparator<String> com = new Comparator<String>(){
			@Override
			public int compare(String o1, String o2) {
				return Integer.compare(o1.length(), o2.length());
			}
		};
		
		TreeSet<String> ts = new TreeSet<>(com);
		
		TreeSet<String> ts2 = new TreeSet<>(new Comparator<String>(){
			@Override
			public int compare(String o1, String o2) {
				return Integer.compare(o1.length(), o2.length());
			}
			
		});
	}
	
	//如今的 Lambda 表達式
	@Test
	public void test2(){
		Comparator<String> com = (x, y) -> Integer.compare(x.length(), y.length());
		TreeSet<String> ts = new TreeSet<>(com);
	}
	
	List<Employee> emps = Arrays.asList(
			new Employee(101, "張三", 18, 9999.99),
			new Employee(102, "李四", 59, 6666.66),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "趙六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);

	//需求:獲取公司中年齡小於 35 的員工信息
	public List<Employee> filterEmployeeAge(List<Employee> emps){
		List<Employee> list = new ArrayList<>();
		
		for (Employee emp : emps) {
			if(emp.getAge() <= 35){
				list.add(emp);
			}
		}
		
		return list;
	}
	
	@Test
	public void test3(){
		List<Employee> list = filterEmployeeAge(emps);
		
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
	
	//需求:獲取公司中工資大於 5000 的員工信息
	public List<Employee> filterEmployeeSalary(List<Employee> emps){
		List<Employee> list = new ArrayList<>();
		
		for (Employee emp : emps) {
			if(emp.getSalary() >= 5000){
				list.add(emp);
			}
		}
		
		return list;
	}
	
	//優化方式一:策略設計模式
	public List<Employee> filterEmployee(List<Employee> emps, MyPredicate<Employee> mp){
		List<Employee> list = new ArrayList<>();
		
		for (Employee employee : emps) {
			if(mp.test(employee)){
				list.add(employee);
			}
		}
		
		return list;
	}
	
	@Test
	public void test4(){
		List<Employee> list = filterEmployee(emps, new FilterEmployeeForAge());
		for (Employee employee : list) {
			System.out.println(employee);
		}
		
		System.out.println("------------------------------------------");
		
		List<Employee> list2 = filterEmployee(emps, new FilterEmployeeForSalary());
		for (Employee employee : list2) {
			System.out.println(employee);
		}
	}
	
	//優化方式二:匿名內部類
	@Test
	public void test5(){
		List<Employee> list = filterEmployee(emps, new MyPredicate<Employee>() {
			@Override
			public boolean test(Employee t) {
				return t.getId() <= 103;
			}
		});
		
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
	
	//優化方式三:Lambda 表達式
	@Test
	public void test6(){
		List<Employee> list = filterEmployee(emps, (e) -> e.getAge() <= 35);
		list.forEach(System.out::println);
		
		System.out.println("------------------------------------------");
		
		List<Employee> list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
		list2.forEach(System.out::println);
	}
	
	//優化方式四:Stream API
	@Test
	public void test7(){
		emps.stream()
			.filter((e) -> e.getAge() <= 35)
			.forEach(System.out::println);
		
		System.out.println("----------------------------------------------");
		
		emps.stream()
			.map(Employee::getName)
			.limit(3)
			.sorted()
			.forEach(System.out::println);
	}
}
複製代碼
/* * 1、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); * * * 2、Lambda 表達式須要「函數式接口」的支持 *只包含一個抽象方法的接口,稱爲函數式接口。你能夠經過 Lambda *表達式來建立該接口的對象。(若 Lambda *表達式拋出一個受檢異常,那麼該異常須要在目標接口的抽象方 *法上進行聲明)。 *咱們能夠在任意函數式接口上使用 @FunctionalInterface 註解, *這樣作能夠檢查它是不是一個函數式接口,同時 javadoc 也會包 *含一條聲明,說明這個接口是一個函數式接口。 *做爲參數傳遞 Lambda 表達式:爲了將 Lambda 表達式做爲參數傳遞,接收Lambda *表達式的參數類型必須是與該 Lambda 表達式兼容的函數式接口的類型。 */
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("hello world!");
	}
	
	@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);
	}
}

複製代碼
@FunctionalInterface
public interface MyFun {

	public Integer getValue(Integer num);
	
}

複製代碼

函數式接口

java內置的四大核心函數式接口數據庫

java內置的四大核心函數式接口

其餘接口設計模式

其餘接口

/* * Java8 內置的四大核心函數式接口 * * Consumer<T> : 消費型接口 * void accept(T t); * * Supplier<T> : 供給型接口 * T get(); * * Function<T, R> : 函數型接口 * R apply(T t); * * Predicate<T> : 斷言型接口 * boolean test(T t); * */
public class TestLambda3 {
	
	//Predicate<T> 斷言型接口:
	@Test
	public void test4(){
		List<String> list = Arrays.asList("Hello", "stream", "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 JAVA是世界上最好的語言 ", (str) -> str.trim());
		System.out.println(newStr);
		
		String subStr = strHandler("JAVA是世界上最好的語言", (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體的操做,已經有實現的方法了,可使用方法引用! (實現抽象方法的參數列表,必須與方法引用方法的參數列表保持一致!) 方法引用:使用操做符 「::」 將方法名和對象或類的名字分隔開來。 
複製代碼
/* * 1、方法引用:若 Lambda 體中的功能,已經有方法提供了實現,可使用方法引用 * (能夠將方法引用理解爲 Lambda 表達式的另一種表現形式) * * 1. 對象的引用 :: 實例方法名 * * 2. 類名 :: 靜態方法名 * * 3. 類名 :: 實例方法名 * * 注意: * ①方法引用所引用的方法的參數列表與返回值類型,須要與函數式接口中抽象方法的參數列表和返回值類型保持一致! * ②若Lambda 的參數列表的第一個參數,是實例方法的調用者,第二個參數(或無參)是實例方法的參數時,格式: ClassName::MethodName */
public class TestMethodRef {
	//類名 :: 實例方法名
	@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;
	}
	
}

複製代碼

構造器引用

格式: ClassName::new 與函數式接口相結合,自動與函數式接口中方法兼容。 能夠把構造器引用賦值給定義的方法,與構造器參數。構造器的參數列表,須要與函數式接口中參數列表保持一致數組

//構造器引用
	@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());
	}
複製代碼

數組引用

類型[] :: new;安全

//數組引用
	@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);
	}
複製代碼

Stream API

Java8中有兩大最爲重要的改變。第一個是 Lambda 表達式;另一 個則是 Stream API(java.util.stream.*)。 Stream 是 Java8 中處理集合的關鍵抽象概念,它能夠指定你但願對 集合進行的操做,能夠執行很是複雜的查找、過濾和映射數據等操做。 使用Stream API 對集合數據進行操做,就相似於使用 SQL 執行的數據庫查詢。也可使用 Stream API 來並行執行操做。簡而言之, Stream API 提供了一種高效且易於使用的處理數據的方式。網絡

什麼是Stream

Stream:數據渠道,用於操做數據源(集合、數組等)所生成的元素序列。 「集合講的是數據,流講的是計算!」 注意:多線程

  1. Stream 本身不會存儲元素。
  2. Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。
  3. Stream 操做是延遲執行的。這意味着他們會等到須要結果的時候才執行。

Stream 操做的三個步驟

  • 建立 Stream。 一個數據源(如:集合、數組),獲取一個流
  • 中間操做。一箇中間操做鏈,對數據源的數據進行處理。
  • 終止操做(終端操做)。一個終止操做,執行中間操做鏈,併產生結果

Stream操做流程

1.建立Steam

1.1 Java8 中的 Collection 接口被擴展,提供了兩個獲取流的方法:app

  • default Stream stream() : 返回一個順序流
  • default Stream parallelStream() : 返回一個並行流

1.2 由數組建立Stream。Java8 中的 Arrays 的靜態方法 stream() 可 以獲取數組流:框架

  • static Stream stream(T[] array): 返回一個流

重載形式,可以處理對應基本類型的數組:dom

  • public static IntStream stream(int[] array)
  • public static LongStream stream(long[] array)
  • public static DoubleStream stream(double[] array)

1.3 由值建立Stream 可使用靜態方法 Stream.of(), 經過顯示值,建立一個流。他能夠接收任意數量的參數。

  • public static Stream of(T... values) : 返回一個流

1.4 由函數建立流:建立無限流

可使用靜態方法 Stream.iterate() 和 Stream.generate(), 建立無限流。

  • 迭代 public static Stream iterate(final T seed, final UnaryOperator f)
  • 生成 public static Stream generate(Supplier s)

2.Steam的中間操做

多箇中間操做能夠鏈接起來造成一個流水線,除非流水 線上觸發終止操做,不然中間操做不會執行任何的處理! 而在終止操做時一次性所有處理,稱爲「惰性求值」。

  • 2.1 篩選與切片

篩選與切片

  • 2.2 映射

映射

  • 2.3 排序

排序

Steam 的終止操做

  • 3.1 查找與匹配 終端操做會從流的流水線生成結果。其結果能夠是任何不是流的 值,例如:List、Integer,甚至是 void 。

查找與匹配

  • 3.2 歸約

歸約
備註:map 和 reduce 的鏈接一般稱爲 map-reduce 模式,因 Google 用它 來進行網絡搜索而出名。

  • 3.3 收集

Collector 接口中方法的實現決定了如何對流執行收集操做(如收 集到 List、Set、Map)。可是 Collectors 實用類提供了不少靜態 方法,能夠方便地建立常見收集器實例,具體方法與實例以下表:

/* * 1、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);
	}
}

複製代碼
/* * 1、 Stream 的操做步驟 * * 1. 建立 Stream * * 2. 中間操做 * * 3. 終止操做 */
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();
	}
	
	/* 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);
	}
}
複製代碼
/* * 1、 Stream 的操做步驟 * * 1. 建立 Stream * * 2. 中間操做 * * 3. 終止操做 */
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();
	}
	
	/* 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());
	}

}

複製代碼
public class TestStreamAPI {
	
	/* 1. 給定一個數字列表,如何返回一個由每一個數的平方構成的列表呢? ,給定【1,2,3,4,5】, 應該返回【1,4,9,16,25】。 */
	@Test
	public void test1(){
		Integer[] nums = new Integer[]{1,2,3,4,5};
		
		Arrays.stream(nums)
			  .map((x) -> x * x)
			  .forEach(System.out::println);
	}

	/* 2. 怎樣用 map 和 reduce 方法數一數流中有多少個Employee呢? */
	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)
	);
	
	@Test
	public void test2(){
		Optional<Integer> count = emps.stream()
			.map((e) -> 1)
			.reduce(Integer::sum);
		
		System.out.println(count.get());
	}
}

複製代碼
//交易員類
public class Trader {

	private String name;
	private String city;

	public Trader() {
	}

	public Trader(String name, String city) {
		this.name = name;
		this.city = city;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	@Override
	public String toString() {
		return "Trader [name=" + name + ", city=" + city + "]";
	}

}
//交易類
public class Transaction {

	private Trader trader;
	private int year;
	private int value;

	public Transaction() {
	}

	public Transaction(Trader trader, int year, int value) {
		this.trader = trader;
		this.year = year;
		this.value = value;
	}

	public Trader getTrader() {
		return trader;
	}

	public void setTrader(Trader trader) {
		this.trader = trader;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Transaction [trader=" + trader + ", year=" + year + ", value="
				+ value + "]";
	}

}

public class TestTransaction {
	
	List<Transaction> transactions = null;
	
	@Before
	public void before(){
		Trader raoul = new Trader("Raoul", "Cambridge");
		Trader mario = new Trader("Mario", "Milan");
		Trader alan = new Trader("Alan", "Cambridge");
		Trader brian = new Trader("Brian", "Cambridge");
		
		transactions = Arrays.asList(
				new Transaction(brian, 2011, 300),
				new Transaction(raoul, 2012, 1000),
				new Transaction(raoul, 2011, 400),
				new Transaction(mario, 2012, 710),
				new Transaction(mario, 2012, 700),
				new Transaction(alan, 2012, 950)
		);
	}
	
	//1. 找出2011年發生的全部交易, 並按交易額排序(從低到高)
	@Test
	public void test1(){
		transactions.stream()
					.filter((t) -> t.getYear() == 2011)
					.sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
					.forEach(System.out::println);
	}
	
	//2. 交易員都在哪些不一樣的城市工做過?
	@Test
	public void test2(){
		transactions.stream()
					.map((t) -> t.getTrader().getCity())
					.distinct()
					.forEach(System.out::println);
	}
	
	//3. 查找全部來自劍橋的交易員,並按姓名排序
	@Test
	public void test3(){
		transactions.stream()
					.filter((t) -> t.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getTrader)
					.sorted((t1, t2) -> t1.getName().compareTo(t2.getName()))
					.distinct()
					.forEach(System.out::println);
	}
	
	//4. 返回全部交易員的姓名字符串,按字母順序排序
	@Test
	public void test4(){
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.forEach(System.out::println);
		
		System.out.println("-----------------------------------");
		
		String str = transactions.stream()
					.map((t) -> t.getTrader().getName())
					.sorted()
					.reduce("", String::concat);
		
		System.out.println(str);
		
		System.out.println("------------------------------------");
		
		transactions.stream()
					.map((t) -> t.getTrader().getName())
					.flatMap(TestTransaction::filterCharacter)
					.sorted((s1, s2) -> s1.compareToIgnoreCase(s2))
					.forEach(System.out::print);
	}
	
	public static Stream<String> filterCharacter(String str){
		List<String> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch.toString());
		}
		
		return list.stream();
	}
	
	//5. 有沒有交易員是在米蘭工做的?
	@Test
	public void test5(){
		boolean bl = transactions.stream()
					.anyMatch((t) -> t.getTrader().getCity().equals("Milan"));
		
		System.out.println(bl);
	}
	
	
	//6. 打印生活在劍橋的交易員的全部交易額
	@Test
	public void test6(){
		Optional<Integer> sum = transactions.stream()
					.filter((e) -> e.getTrader().getCity().equals("Cambridge"))
					.map(Transaction::getValue)
					.reduce(Integer::sum);
		
		System.out.println(sum.get());
	}
	
	
	//7. 全部交易中,最高的交易額是多少
	@Test
	public void test7(){
		Optional<Integer> max = transactions.stream()
					.map((t) -> t.getValue())
					.max(Integer::compare);
		
		System.out.println(max.get());
	}
	
	//8. 找到交易額最小的交易
	@Test
	public void test8(){
		Optional<Transaction> op = transactions.stream()
					.min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()));
		
		System.out.println(op.get());
	}

}


複製代碼

並行流與串行流

並行流就是把一個內容分紅多個數據塊,並用不一樣的線程分別處理每一個數據塊的流。

Java 8 中將並行進行了優化,咱們能夠很容易的對數據進行並行操做。Stream API 能夠聲明性地經過 parallel() 與 sequential() 在並行流與順序流之間進行切換。

瞭解 Fork/Join 框架

Fork/Join 框架:就是在必要的狀況下,將一個大任務,進行拆分(fork)成若干個 小任務(拆到不可再拆時),再將一個個的小任務運算的結果進行 join 彙總.

Fork/Join 框架與傳統線程池的區別

採用 「工做竊取」模式(work-stealing): 當執行新的任務時它能夠將其拆分,分紅更小的任務執行,並將小任務加到線 程隊列中,而後再從一個隨機線程的隊列中偷一個並把它放在本身的隊列中。

相對於通常的線程池實現,fork/join框架的優點體如今對其中包含的任務的 處理方式上.在通常的線程池中,若是一個線程正在執行的任務因爲某些緣由 沒法繼續運行,那麼該線程會處於等待狀態。而在fork/join框架實現中,若是 某個子問題因爲等待另一個子問題的完成而沒法繼續運行,那麼處理該子 問題的線程會主動尋找其餘還沒有運行的子問題來執行.這種方式減小了線程 的等待時間,提升了性能。

public class ForkJoinCalculate extends RecursiveTask<Long>{


	private static final long serialVersionUID = -1L;
	
	private long start;
	private long end;
	
	private static final long THRESHOLD = 10000L; //臨界值
	
	public ForkJoinCalculate(long start, long end) {
		this.start = start;
		this.end = end;
	}
	
	@Override
	protected Long compute() {
		long length = end - start;
		
		if(length <= THRESHOLD){
			long sum = 0;
			
			for (long i = start; i <= end; i++) {
				sum += i;
			}
			
			return sum;
		}else{
			long middle = (start + end) / 2;
			
			ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
			left.fork(); //拆分,並將該子任務壓入線程隊列
			
			ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
			right.fork();
			
			return left.join() + right.join();
		}
		
	}

}
複製代碼
public class TestForkJoin {
	
	@Test
	public void test1(){
		long start = System.currentTimeMillis();
		
		ForkJoinPool pool = new ForkJoinPool();
		ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
		
		long sum = pool.invoke(task);
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
	}
	
	@Test
	public void test2(){
		long start = System.currentTimeMillis();
		
		long sum = 0L;
		
		for (long i = 0L; i <= 10000000000L; i++) {
			sum += i;
		}
		
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //34-3174-3132-4227-4223-31583
	}
	
	@Test
	public void test3(){
		long start = System.currentTimeMillis();
		
		Long sum = LongStream.rangeClosed(0L, 10000000000L)
							 .parallel()
							 .sum();
		
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //2061-2053-2086-18926
	}

}
複製代碼

Optional 類

Optional 類(java.util.Optional) 是一個容器類,表明一個值存在或不存在, 原來用 null 表示一個值不存在,如今 Optional 能夠更好的表達這個概念。而且 能夠避免空指針異常。

經常使用方法: Optional.of(T t) : 建立一個 Optional 實例

Optional.empty() : 建立一個空的 Optional 實例

Optional.ofNullable(T t):若 t 不爲 null,建立 Optional 實例,不然建立空實例

isPresent() : 判斷是否包含值

orElse(T t) : 若是調用對象包含值,返回該值,不然返回t

orElseGet(Supplier s) :若是調用對象包含值,返回該值,不然返回 s 獲取的值

map(Function f): 若是有值對其處理,並返回處理後的Optional,不然返回 Optional.empty() flatMap(Function mapper):與 map 相似,要求返回值必須是Optional

public class Godness {

	private String name;

	public Godness() {
	}

	public Godness(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Godness [name=" + name + "]";
	}

}


public class Man {

	private Godness god;

	public Man() {
	}

	public Man(Godness god) {
		this.god = god;
	}

	public Godness getGod() {
		return god;
	}

	public void setGod(Godness god) {
		this.god = god;
	}

	@Override
	public String toString() {
		return "Man [god=" + god + "]";
	}

}

//注意:Optional 不能被序列化
public class NewMan {

	private Optional<Godness> godness = Optional.empty();
	
	private Godness god;
	
	public Optional<Godness> getGod(){
		return Optional.of(god);
	}

	public NewMan() {
	}

	public NewMan(Optional<Godness> godness) {
		this.godness = godness;
	}

	public Optional<Godness> getGodness() {
		return godness;
	}

	public void setGodness(Optional<Godness> godness) {
		this.godness = godness;
	}

	@Override
	public String toString() {
		return "NewMan [godness=" + godness + "]";
	}

}
/* * 1、Optional 容器類:用於儘可能避免空指針異常 * Optional.of(T t) : 建立一個 Optional 實例 * Optional.empty() : 建立一個空的 Optional 實例 * Optional.ofNullable(T t):若 t 不爲 null,建立 Optional 實例,不然建立空實例 * isPresent() : 判斷是否包含值 * orElse(T t) : 若是調用對象包含值,返回該值,不然返回t * orElseGet(Supplier s) :若是調用對象包含值,返回該值,不然返回 s 獲取的值 * map(Function f): 若是有值對其處理,並返回處理後的Optional,不然返回 Optional.empty() * flatMap(Function mapper):與 map 相似,要求返回值必須是Optional */
public class TestOptional {
	
	@Test
	public void test4(){
		Optional<Employee> op = Optional.of(new Employee(101, "張三", 18, 9999.99));
		
		Optional<String> op2 = op.map(Employee::getName);
		System.out.println(op2.get());
		
		Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));
		System.out.println(op3.get());
	}
	
	@Test
	public void test3(){
		Optional<Employee> op = Optional.ofNullable(new Employee());
		
		if(op.isPresent()){
			System.out.println(op.get());
		}
		
		Employee emp = op.orElse(new Employee("張三"));
		System.out.println(emp);
		
		Employee emp2 = op.orElseGet(() -> new Employee());
		System.out.println(emp2);
	}
	
	@Test
	public void test2(){
		/*Optional<Employee> op = Optional.ofNullable(null); System.out.println(op.get());*/
		
// Optional<Employee> op = Optional.empty();
// System.out.println(op.get());
	}

	@Test
	public void test1(){
		Optional<Employee> op = Optional.of(new Employee());
		Employee emp = op.get();
		System.out.println(emp);
	}
	
	@Test
	public void test5(){
		Man man = new Man();
		
		String name = getGodnessName(man);
		System.out.println(name);
	}
	
	//需求:獲取一個男人心中女神的名字
	public String getGodnessName(Man man){
		if(man != null){
			Godness g = man.getGod();
			
			if(g != null){
				return g.getName();
			}
		}
		
		return "蒼老師";
	}
	
	//運用 Optional 的實體類
	@Test
	public void test6(){
		Optional<Godness> godness = Optional.ofNullable(new Godness("林志玲"));
		
		Optional<NewMan> op = Optional.ofNullable(new NewMan(godness));
		String name = getGodnessName2(op);
		System.out.println(name);
	}
	
	public String getGodnessName2(Optional<NewMan> man){
		return man.orElse(new NewMan())
				  .getGodness()
				  .orElse(new Godness("蒼老師"))
				  .getName();
	}
}


複製代碼

接口中的默認方法與靜態方法

默認方法

Java 8中容許接口中包含具備具體實現的方法,該方法稱爲 「默認方法」,默認方法使用 default 關鍵字修飾。

接口默認方法的」類優先」原則 若一個接口中定義了一個默認方法,而另一個父類或接口中 又定義了一個同名的方法時

  • 選擇父類中的方法。若是一個父類提供了具體的實現,那麼 接口中具備相同名稱和參數的默認方法會被忽略。
  • 接口衝突。若是一個父接口提供一個默認方法,而另外一個接 口也提供了一個具備相同名稱和參數列表的方法(無論方法 是不是默認方法),那麼必須覆蓋該方法來解決衝突

靜態方法

Java8 中,接口中容許添加靜態方法。

public interface MyInterface1 {
	
	default String getName(){
		return "哈哈哈";
	}

}

public interface MyInterface2 {
	
	default String getName(){
		return "呵呵呵";
	}
	
	public static void show(){
		System.out.println("接口中的靜態方法");
	}

}

public class MyClass {
	
	public String getName(){
		return "嘿嘿嘿";
	}

}


public class SubClass /*extends MyClass*/ implements MyFun, MyInterface{

	@Override
	public String getName() {
		return MyInterface.super.getName();
	}

}

public class TestDefaultInterface {
	
	public static void main(String[] args) {
		SubClass sc = new SubClass();
		System.out.println(sc.getName());
		
		MyInterface.show();
	}

}
複製代碼

新的時間日期API

使用 LocalDate、LocalTime、LocalDateTime

LocalDate、LocalTime、LocalDateTime 類的實 例是不可變的對象,分別表示使用 ISO-8601日 歷系統的日期、時間、日期和時間。它們提供 了簡單的日期或時間,並不包含當前的時間信 息。也不包含與時區相關的信息。

注:ISO-8601日曆系統是國際標準化組織制定的現代公民的日期和時間的表示法

Instant 時間戳

用於「時間戳」的運算。它是以Unix元年(傳統 的設定爲UTC時區1970年1月1日午夜時分)開始 所經歷的描述進行運算

Duration 和 Period

  • Duration:用於計算兩個「時間」間隔
  • Period:用於計算兩個「日期」間隔

日期的操縱

  • TemporalAdjuster : 時間校訂器。有時咱們可能須要獲 取例如:將日期調整到「下個週日」等操做。
  • TemporalAdjusters : 該類經過靜態方法提供了大量的常 用 TemporalAdjuster 的實現。

解析與格式化

java.time.format.DateTimeFormatter 類:該類提供了三種 格式化方法:

  • 預約義的標準格式
  • 語言環境相關的格式
  • 自定義的格式

時區的處理

Java8 中加入了對時區的支持,帶時區的時間爲分別爲: ZonedDate、ZonedTime、ZonedDateTime 其中每一個時區都對應着 ID,地區ID都爲 「{區域}/{城市}」的格式 例如 :Asia/Shanghai 等

ZoneId:該類中包含了全部的時區信息 getAvailableZoneIds() : 能夠獲取全部時區時區信息 of(id) : 用指定的時區信息獲取 ZoneId 對象

與傳統日期處理的轉換

public class DateFormatThreadLocal {
	
	private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
		
		protected DateFormat initialValue(){
			return new SimpleDateFormat("yyyyMMdd");
		}
		
	};
	
	public static final Date convert(String source) throws ParseException{
		return df.get().parse(source);
	}

}
public class TestSimpleDateFormat {
	
	public static void main(String[] args) throws Exception {
		
		/*SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Callable<Date> task = new Callable<Date>() { @Override public Date call() throws Exception { return sdf.parse("20161121"); } }; ExecutorService pool = Executors.newFixedThreadPool(10); List<Future<Date>> results = new ArrayList<>(); for (int i = 0; i < 10; i++) { results.add(pool.submit(task)); } for (Future<Date> future : results) { System.out.println(future.get()); } pool.shutdown();*/
		
		//解決多線程安全問題
		/*Callable<Date> task = new Callable<Date>() { @Override public Date call() throws Exception { return DateFormatThreadLocal.convert("20161121"); } }; ExecutorService pool = Executors.newFixedThreadPool(10); List<Future<Date>> results = new ArrayList<>(); for (int i = 0; i < 10; i++) { results.add(pool.submit(task)); } for (Future<Date> future : results) { System.out.println(future.get()); } pool.shutdown();*/
		
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
		
		Callable<LocalDate> task = new Callable<LocalDate>() {

			@Override
			public LocalDate call() throws Exception {
				LocalDate ld = LocalDate.parse("20161121", dtf);
				return ld;
			}
			
		};

		ExecutorService pool = Executors.newFixedThreadPool(10);
		
		List<Future<LocalDate>> results = new ArrayList<>();
		
		for (int i = 0; i < 10; i++) {
			results.add(pool.submit(task));
		}
		
		for (Future<LocalDate> future : results) {
			System.out.println(future.get());
		}
		
		pool.shutdown();
	}

}
public class TestLocalDateTime {
	
	//6.ZonedDate、ZonedTime、ZonedDateTime : 帶時區的時間或日期
	@Test
	public void test7(){
		LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
		System.out.println(ldt);
		
		ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
		System.out.println(zdt);
	}
	
	@Test
	public void test6(){
		Set<String> set = ZoneId.getAvailableZoneIds();
		set.forEach(System.out::println);
	}

	
	//5. DateTimeFormatter : 解析和格式化日期或時間
	@Test
	public void test5(){
// DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
		
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
		
		LocalDateTime ldt = LocalDateTime.now();
		String strDate = ldt.format(dtf);
		
		System.out.println(strDate);
		
		LocalDateTime newLdt = ldt.parse(strDate, dtf);
		System.out.println(newLdt);
	}
	
	//4. TemporalAdjuster : 時間校訂器
	@Test
	public void test4(){
	LocalDateTime ldt = LocalDateTime.now();
		System.out.println(ldt);
		
		LocalDateTime ldt2 = ldt.withDayOfMonth(10);
		System.out.println(ldt2);
		
		LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
		System.out.println(ldt3);
		
		//自定義:下一個工做日
		LocalDateTime ldt5 = ldt.with((l) -> {
			LocalDateTime ldt4 = (LocalDateTime) l;
			
			DayOfWeek dow = ldt4.getDayOfWeek();
			
			if(dow.equals(DayOfWeek.FRIDAY)){
				return ldt4.plusDays(3);
			}else if(dow.equals(DayOfWeek.SATURDAY)){
				return ldt4.plusDays(2);
			}else{
				return ldt4.plusDays(1);
			}
		});
		
		System.out.println(ldt5);
		
	}
	
	//3.
	//Duration : 用於計算兩個「時間」間隔
	//Period : 用於計算兩個「日期」間隔
	@Test
	public void test3(){
		Instant ins1 = Instant.now();
		
		System.out.println("--------------------");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
		}
		
		Instant ins2 = Instant.now();
		
		System.out.println("所耗費時間爲:" + Duration.between(ins1, ins2));
		
		System.out.println("----------------------------------");
		
		LocalDate ld1 = LocalDate.now();
		LocalDate ld2 = LocalDate.of(2011, 1, 1);
		
		Period pe = Period.between(ld2, ld1);
		System.out.println(pe.getYears());
		System.out.println(pe.getMonths());
		System.out.println(pe.getDays());
	}
	
	//2. Instant : 時間戳。 (使用 Unix 元年 1970年1月1日 00:00:00 所經歷的毫秒值)
	@Test
	public void test2(){
		Instant ins = Instant.now();  //默認使用 UTC 時區
		System.out.println(ins);
		
		OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
		System.out.println(odt);
		
		System.out.println(ins.getNano());
		
		Instant ins2 = Instant.ofEpochSecond(5);
		System.out.println(ins2);
	}
	
	//1. LocalDate、LocalTime、LocalDateTime
	@Test
	public void test1(){
		LocalDateTime ldt = LocalDateTime.now();
		System.out.println(ldt);
		
		LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
		System.out.println(ld2);
		
		LocalDateTime ldt3 = ld2.plusYears(20);
		System.out.println(ldt3);
		
		LocalDateTime ldt4 = ld2.minusMonths(2);
		System.out.println(ldt4);
		
		System.out.println(ldt.getYear());
		System.out.println(ldt.getMonthValue());
		System.out.println(ldt.getDayOfMonth());
		System.out.println(ldt.getHour());
		System.out.println(ldt.getMinute());
		System.out.println(ldt.getSecond());
	}

}

複製代碼

重複註解與類型註解

Java 8對註解處理提供了兩點改進:可重複的註解及可用於類 型的註解。

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})//能夠修飾的目標
@Retention(RetentionPolicy.RUNTIME)//生命週期
public @interface MyAnnotations {
    MyAnnotation[] value();
}

@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER})//能夠修飾的目標
@Retention(RetentionPolicy.RUNTIME)//生命週期
public @interface MyAnnotation {
    String value() default "hello Annotation";
}
public class TestAnnotation {

    //checker framework框架提供此註解
    private /*@NonNull*/ Object obj=null;

    @Test
    public void test1() throws NoSuchMethodException, SecurityException{
        Class<TestAnnotation> clazz=TestAnnotation.class;
        Method m1=clazz.getMethod("show");
        MyAnnotation[] mas=m1.getAnnotationsByType(MyAnnotation.class);
        for(MyAnnotation myAnnotation:mas){
            System.out.println(myAnnotation.value());
        }
    }

    @MyAnnotation("Hello")
    @MyAnnotation("world")
    public void show(@MyAnnotation("abc")String str){

    }
}
複製代碼
相關文章
相關標籤/搜索