package basic._04.coll_comparator;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.junit.Test;

import static org.junit.Assert.*;
import static org.hamcrest.core.Is.*;

public class Comparator_Test_J {
	
	/**
	 * [API 8以前]
	 * Comparatorを実装したクラスを利用したソート
	 * 
	 * シナリオ：人物の情報が格納されたリストを年齢でソートする
	 * 着眼点： 8以前では主に Comparatorを実装した実現したが、そもそもComparatorの責任範囲は関数相当であった。
	 */
	@SuppressWarnings("unchecked")
	@Test
	public void test() {
		final List<Person> personList = 
				Arrays.asList(
						new Person("Alice", 20),
						new Person("James", 35),
						new Person("Tonny", 50),
						new Person("Jack",  15));
		
		// ソート処理。右の処理と同等。Collections.sort(list, c);
		personList.sort(new PersonAgeComparator<Person>());
		
		assertThat(personList, is(Arrays.asList(
				new Person("Jack",  15),
				new Person("Alice", 20),
				new Person("James", 35),
				new Person("Tonny", 50))));
	}
	
	/**
	 * [API 8以降]
	 * 関数を利用して実現したソート (関数の実装は Comparatorと同等)
	 * 
	 * シナリオ：(同上)
	 * 着眼点： 関数を利用することで、コードは簡素化された。
	 * 		  但し、8以前で利用した様な汎用的なComparatorは無いので、比較処理を使い回す際には
	 *        Function自体を変数として宣言しておき、適宜参照を配分させる必要がある。
	 */
	@Test
	public void test2() {
		final List<Person> personList = 
				Arrays.asList(
						new Person("Alice", 20),
						new Person("James", 35),
						new Person("Tonny", 50),
						new Person("Jack",  15));
		
		final List<Person> sortedList = 
				personList.stream().sorted(
						(p1, p2) -> p1.age() - p2.age()).collect(Collectors.toList());
		
		assertThat(sortedList, is(Arrays.asList(
				new Person("Jack",  15),
				new Person("Alice", 20),
				new Person("James", 35),
				new Person("Tonny", 50))));
	}
	
	/**
	 * [API 8以降]
	 * 関数を利用して実現したソート (メソッド参照により実現)
	 * 
	 * シナリオ：(同上)
	 * 着眼点： comparator.compare と同等の役割を持つメソッドの参照により参照
	 */
	@Test
	public void test3() {
		final List<Person> personList = 
				Arrays.asList(
						new Person("Alice", 20),
						new Person("James", 35),
						new Person("Tonny", 50),
						new Person("Jack",  15));
		
		// static method(arg1, arg2) の場合、比較対象が arg1, arg2に割り当てられる。
		final List<Person> sortedListA =
				personList.stream().sorted(Person::isOlderThanStatic).collect(Collectors.toList());
		
		assertThat(sortedListA, is(Arrays.asList(
				new Person("Jack",  15),
				new Person("Alice", 20),
				new Person("James", 35),
				new Person("Tonny", 50))));
		
		// instance obj1.method(arg1) の場合、比較対象が obj1, arg1に割り当てられる。
		final List<Person> sortedListB =
				personList.stream().sorted(Person::isOlderThan).collect(Collectors.toList());
		
		assertThat(sortedListB, is(Arrays.asList(
				new Person("Jack",  15),
				new Person("Alice", 20),
				new Person("James", 35),
				new Person("Tonny", 50))));		
	}
	
	/**
	 * [API 8以降]
	 * 関数を利用して実現したソート (反転版のComparatorを簡易作成)
	 * 
	 * シナリオ：(同上)
	 * 着眼点： comparator.compare と同等の役割を持つメソッドの参照により参照
	 */
	public void test4() {
		final List<Person> personList = 
				Arrays.asList(
						new Person("Alice", 20),
						new Person("James", 35),
						new Person("Tonny", 50),
						new Person("Jack",  15));
		
		final Comparator<Person> yougerComparator = (person1, person2) -> person1.isOlderThan(person2);
		final Comparator<Person> olderComparator  = yougerComparator.reversed();
		
		final List<Person> sortedList =
				personList.stream().sorted(olderComparator).collect(Collectors.toList());
		
		assertThat(sortedList, is(Arrays.asList(
				new Person("Tonny", 50),
				new Person("James", 35),
				new Person("Alice", 20),
				new Person("Jack",  15))));
	}
	
}

@@ -492,21 +492,34 @@
 oid test
+OldComparator
 () %7B%0A
-
 %09%09final 
@@ -1208,17 +1208,30 @@
 oid test
-2
+FuncComparator
 () %7B%0A%09%09f
@@ -1865,17 +1865,41 @@
 oid test
-3
+FuncComparatorByMethodRef
 () %7B%0A%09%09f
@@ -2916,16 +2916,23 @@
 %E5%8F%82%E7%85%A7%0A%09 */%0A
+%09@Test%0A
 %09public 
@@ -2940,17 +2940,49 @@
 oid test
-4
+FuncComparatorByMethodRefReversed
 () %7B%0A%09%09f

テストメソッド名を修正 @Testが抜けている部分があったためそれを追加