lambdas

Collections的sort比较:Comparator、lambda expression、Comparator.comparing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class CollectionsSort {
public static void main(String[] args) {
List<String> names = Arrays.asList("shekhar", "rahul", "sameer");
// using Comparator
Collections.sort(names, new Comparator<String>() {

// (first, second) - (o1, o2)
@Override
public int compare(String o1, String o2) {
// first.length() - second.length()
return ((null == o1 ? "" : o1).length() - (null == o2 ? "" : o2).length());
}
});
System.out.println(names);

names = Arrays.asList("shekhar", "rahul", "sameer");
// using lambda expression 相当于传递一个没有方法名的compare方法
// Collections.sort(names, (first, second) -> first.length() - second.length());
Collections.sort(names, (first, second) -> {
return ((null == first ? "" : first).length() - (null == second ? "" : second).length());
});
System.out.println(names);

names = Arrays.asList("shekhar", "rahul", "sameer");
// using Comparator.comparing -- method references
Collections.sort(names, Comparator.comparing(String::length));
System.out.println(names);
}
}

How?:JDK8的Runnable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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();
}

只有一个抽象方法且标注@FunctionalInterface注解的接口才可以使用lambda expressions【Object类中的相同方法在接口的定义中除外-equals、toString等不影响@FunctionalInterface】。

Java 8 lambda expressions的实现和编译机制

不使用内部类实现的两个原因
  1. 性能:如果使用内部类,每个lambda表达式都会编译成字节码文件(class)存储在磁盘上,这些文件在JVM启动的时候被加载,会增加JVM的启动时间,因为所有的字节码文件都需要在使用之前进行首次加载和校验
  2. 可扩展:如果使用内部类,lambda在未来想要改变实现方式时会受到一定的限制
  3. CallSite
使用动态调用机制【Java7引入】
  1. 当使用javac编译代码的时候,它会捕捉到lambda表达式,然后生成一个invokedynamic(lambda工厂)CallSite,当invokedynamic callsite被调用时返回一个lambda表达式转化的函数式接口的实例
  2. Collections.sort的字节码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static void main(java.lang.String[]);
Code:
0: iconst_3
1: anewarray #2 // class java/lang/String
4: dup
5: iconst_0
6: ldc #3 // String shekhar
8: aastore
9: dup
10: iconst_1
11: ldc #4 // String rahul
13: aastore
14: dup
15: iconst_2
16: ldc #5 // String sameer
18: aastore
19: invokestatic #6 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
22: astore_1
23: invokedynamic #7, 0 // InvokeDynamic #0:compare:()Ljava/util/Comparator;
28: astore_2
29: aload_1
30: aload_2
31: invokestatic #8 // Method java/util/Collections.sort:(Ljava/util/List;Ljava/util/Comparator;)V
34: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;
37: aload_1
38: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
41: return
}
lambda-translation

Java8提供的函数式接口:java.util.function

  1. java.util.function.Predicate 条件检查:判断

    1
    2
    3
    4
    5
    6
    7
    @FunctionalInterface
    public interface Predicate<T> {
    boolean test(T var1);
    ...
    }

    Predicate<String> namesStartingWithS = name -> name.startsWith("s");
  2. java.util.function.Consumer 只处理,无返回结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @FunctionalInterface
    public interface Consumer<T> {

    /**
    * Performs this operation on the given argument.
    *
    * @param t the input argument
    */
    void accept(T t);
    }

    Consumer<String> messageConsumer = message -> System.out.println(message);
  3. java.util.function.Function<T,R> 处理且有返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @FunctionalInterface
    public interface Function<T, R> {

    /**
    * Applies this function to the given argument.
    *
    * @param t the function argument
    * @return the function result
    */
    R apply(T t);
    }

    Function<String, String> toUpperCase = name -> name.toUpperCase();
  4. java.util.function.Supplier 没有参数,只有返回结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @FunctionalInterface
    public interface Supplier<T> {

    /**
    * Gets a result.
    *
    * @return a result
    */
    T get();
    }

    Supplier<String> uuidGenerator= () -> UUID.randomUUID().toString();

方法引用 Object::method

  1. method references 如 String::length and so on
  2. static method references 如 Collections::max
  3. instance method references 如 String::concat

原文链接

邵志鹏 wechat
扫一扫上面的二维码关注我的公众号
0%