@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
像Runnable,Callable等有且只有一個抽象方法的接口,一般稱爲單一抽象方法接口,我們平常使用它的時候,比較習慣於使用一個內部類,這至少也要幾行的代碼,如下:
public class AnonymousInnerClassTest {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("A thread created and running ...");
}
}).start();
}
}
如果我們聲明爲函數式接口,再結合Lambda表達式,那麼一行代碼就可以搞定,比較方便。如下代碼:
/*
* Implementing the interface by creating an
* anonymous inner class versus using
* lambda expression.
*/
public class SimpleFunInterfaceTest {
public static void main(String[] args) {
carryOutWork(new SimpleFuncInterface() {
@Override
public void doWork() {
System.out.println("Do work in SimpleFun impl...");
}
});
carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
}
public static void carryOutWork(SimpleFuncInterface sfi){
sfi.doWork();
}
}
輸出爲:
Do work in SimpleFun impl...
Do work in lambda exp impl...
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
default public void doSomeWork(){
System.out.println("Doing some work in interface impl...");
}
default public void doSomeOtherWork(){
System.out.println("Doing some other work in interface impl...");
}
}
總結:好處在哪裏?
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
......
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
......
}
Predicate:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
......
}
Thread oldSchool = new Thread( new Runnable () {
@Override
public void run() {
System.out.println("This is from an anonymous class.");
}
});
Thread gaoDuanDaQiShangDangCi = new Thread( () -> {
System.out.println("This is from an anonymous method (lambda exp).");
});
List<Shape> shapes = ...
shapes.stream()
.filter(s -> s.getColor() == BLUE)
.forEach(s -> s.setColor(RED));
public void distinctPrimary(String... numbers) {
List<String> l = Arrays.asList(numbers);
List<Integer> r = l.stream()
.map(e -> new Integer(e))
.filter(e -> Primes.isPrime(e))
.distinct()
.collect(Collectors.toList());
System.out.println("distinctPrimary result is: " + r);
}
你可能會覺得在這個例子裏,List l被迭代了好多次,map,filter,distinct都分別是一次循環,效率會不好。實際並非如此。這些返回另一個Stream的方法都是“懶 (lazy)”的,而最後返回最終結果的collect方法則是“急(eager)”的。在遇到eager方法之前,lazy的方法不會執行。
當遇到eager方法時,前面的lazy方法纔會被依次執行。而且是管道貫通式執行。這意味着每一個元素依次通過這些管道。例如有個元素“3”,首 先它被map成整數型3;然後通過filter,發現是素數,被保留下來;又通過distinct,如果已經有一個3了,那麼就直接丟棄,如果還沒有則保 留。這樣,3個操作其實只經過了一次循環。
//給出一個String類型的數組,找出其中各個素數,並統計其出現次數
public void primaryOccurrence(String... numbers) {
List<String> l = Arrays.asList(numbers);
Map<Integer, Integer> r = l.stream()
.map(e -> new Integer(e))
.filter(e -> Primes.isPrime(e))
.collect( Collectors.groupingBy(p->p, Collectors.summingInt(p->1)) );
System.out.println("primaryOccurrence result is: " + r);
}
注意這一行:
Collectors.groupingBy(p->p, Collectors.summingInt(p->1))
//給出一個String類型的數組,求其中所有不重複素數的和
public void distinctPrimarySum(String... numbers) {
List<String> l = Arrays.asList(numbers);
int sum = l.stream()
.map(e -> new Integer(e))
.filter(e -> Primes.isPrime(e))
.distinct()
.reduce(0, (x,y) -> x+y); // equivalent to .sum()
System.out.println("distinctPrimarySum result is: " + sum);
}
流有很多預定義的reduce操作,如sum(),max(),min()等。
// 統計年齡在25-35歲的男女人數、比例
public void boysAndGirls(List<Person> persons) {
Map<Integer, Integer> result = persons.parallelStream().filter(p -> p.getAge()>=25 && p.getAge()<=35).
collect(
Collectors.groupingBy(p->p.getSex(), Collectors.summingInt(p->1))
);
System.out.print("boysAndGirls result is " + result);
System.out.println(", ratio (male : female) is " + (float)result.get(Person.MALE)/result.get(Person.FEMALE));
}
Ps:
List persons = ..
//串行操作
Stream stream=persons.stream();
//並行操作
Stream parallelStream=persons.parallelStream();
interface ITest {
public default void sayHello(){
System.out.println("Hello");
}
}
public class Test implements ITest{
public static void main(String[] args) {
new Test().sayHello();
}
}