java - 使用lambda表达式(匿名内部类)传参是否有性能问题?
阿神
阿神 2017-04-18 10:53:20
0
3
1144

编程有一条原则如下:

避免创建不必要的对象:最好能重用对象,而不要在每次需要的时候就创建一个相同功能的新对象。

请看如下代码:

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");

 // 1、匿名内部类
Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return b.compareTo(a);
    }
});

//2、lambda表达式
Collections.sort(names, (a, b) -> b.compareTo(a));

是不是每次排序都创建了一个新的Comparator对象,导致性能降低?那么还主张使用Lambda表达式吗

阿神
阿神

闭关修行中......

membalas semua(3)
Peter_Zhu

Jawab dahulu soalan anda:
Adakah objek Comparator baharu dicipta setiap kali mengisih, menyebabkan prestasi berkurangan? Jadi adakah anda masih menyokong penggunaan ungkapan Lambda?
Tidak, saya menyokong

  1. Sebab asas
    Lamdba bermakna ia bukan gula sintaksis untuk kelas dalaman tanpa nama sama sekali, maksudnya, pelaksanaan asas ungkapan Lambda bukanlah pelaksanaan kelas dalaman tanpa nama. Mereka sebenarnya dua perkara

  2. Bagaimana untuk membuktikannya?
    Kelas dalaman tanpa nama sebenarnya akan menjana fail kelas semasa penyusunan, dinamakan dengan nombor ClassName$, jadi jika lapisan bawah ungkapan Lamdba juga dilaksanakan oleh kelas dalaman tanpa nama, ia pasti akan menghasilkan fail Dalam yang serupa
    Oleh itu, kami hanya menulis contoh anda dalam kelas di bawah pakej yang berbeza, dan kemudian semak kesan terkumpul
    Kelas dalaman tanpa nama melaksanakan InnerTest


    Ini adalah fail kelas, anda boleh lihat ada dua

    ekspresi lambda LamdbaTest

    Walau bagaimanapun, terdapat hanya satu fail kelas


    Jadi hanya ada satu kebenaran, haha, jelas sekali, ini bukan perkara yang sama sama sekali

  3. Bagaimanakah ungkapan Lamdba dilaksanakan?
    Kita boleh melihat kod bait mereka, supaya perbezaan asas ditunjukkan sepenuhnya
    InnerTest

    LamdbaTest

    Anda dapat melihat bahawa arahan yang digunakan oleh kedua-duanya adalah berbeza Apabila menghuraikan ungkapan Lamdba, arahan invokedynamic baharu dalam Java 7 digunakan Jika anda sudah biasa dengan arahan ini, anda mungkin memahaminya dengan serta-merta biasa dengannya, anda boleh bertanya kepada Du Niang
    Tetapi anda boleh memahaminya secara langsung daripada nama arahan ini: Panggilan dinamik
    Oleh itu, tidak seperti kelas dalaman tanpa nama yang disusun ke dalam fail kelas, Lamdba Ungkapan disusun menjadi kaedah statik Kita boleh melihatnya semula dengan melihat -p Kaedah yang dijana dinamakan lambda$main

所以结合之前两个反编译的结果可以看到,lamdba表达式运行整体思路大致如下  
    1. lamdba表达式被编译生成当前类的一个私有静态方法  
    2. 在原调用Lamdba方法的地方编译成了一个invokedynamic指令调用,同时呢也生成了一个对应的BootstrapMethod  
    3. 当lamdba表达式被JVM执行,也就是碰到2中说到的invokedynamic指令,该指令引导调用LambdaMetafactory.metafactory方法,该方法返回一个CallSite实例
    4. 而这个CallSite实例中的target对象,也就是直接引用到一个MethodHandle实例,而这个MethodHandle实例会调用到1中生成的静态方法,在上面的例子就是`lambda$mainrrreee`这个方法,完成整个lamdba表达式的使用  
  1. Seperkara lagi
    Malah, anda dapat melihat bahawa ungkapan lambba sememangnya jauh lebih baik daripada kelas dalaman tanpa nama dalam erti kata, sama ada prestasi, kebolehbacaan atau trend umum~ Haha, saya mahu untuk mengatakan trend umum , kerana ungkapan lamdba boleh dioptimumkan dalam ruang yang lebih luas Bagaimanapun, saya sudah biasa menggunakannya dalam java, dan saya sangat suka

.
阿神
  1. Setiap pengisihan tidak mencipta objek Comparator baharu Secara amnya, sebaik sahaja kejadian yang sepadan dengan ungkapan Lambda dijana dalam ingatan, JVM akan Contoh ini akan digunakan semula di bawah. Untuk arahan khusus, sila rujuk pautan ini: Penilaian Masa Larian bagi Ungkapan Lambda

  2. Atas alasan ia boleh meningkatkan kebolehbacaan program dan kecekapan pembangunan, adalah disyorkan untuk menggunakan ungkapan Lambda

刘奇
  1. Anda boleh mengisytiharkan objek kelas tanpa nama secara statik di dalam ungkapan Lambda

  2. Objek kecil yang datang dan pergi bukan masalah besar untuk JVM;

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan