Dalam proyek kami, kami bermigrasi ke java 8 dan kami menguji fitur-fitur baru itu.
Pada proyek saya, saya menggunakan predikat dan fungsi Jambu biji untuk memfilter dan mengubah beberapa koleksi menggunakan Collections2.transform
dan Collections2.filter
.
Pada migrasi ini saya perlu mengubah misalnya kode jambu biji ke java 8 perubahan. Jadi, perubahan yang saya lakukan adalah seperti:
List<Integer> naturals = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10,11,12,13);
Function <Integer, Integer> duplicate = new Function<Integer, Integer>(){
@Override
public Integer apply(Integer n)
{
return n * 2;
}
};
Collection result = Collections2.transform(naturals, duplicate);
Untuk...
List<Integer> result2 = naturals.stream()
.map(n -> n * 2)
.collect(Collectors.toList());
Menggunakan jambu biji saya sangat nyaman men-debug kode karena saya dapat men-debug setiap proses transformasi tetapi perhatian saya adalah bagaimana men-debug misalnya .map(n -> n*2)
.
Menggunakan debugger saya dapat melihat beberapa kode seperti:
@Hidden
@DontInline
/** Interpretively invoke this form on the given arguments. */
Object interpretWithArguments(Object... argumentValues) throws Throwable {
if (TRACE_INTERPRETER)
return interpretWithArgumentsTracing(argumentValues);
checkInvocationCounter();
assert(arityCheck(argumentValues));
Object[] values = Arrays.copyOf(argumentValues, names.length);
for (int i = argumentValues.length; i < values.length; i++) {
values[i] = interpretName(names[i], values);
}
return (result < 0) ? null : values[result];
}
Tetapi tidak sesulit Jambu untuk men-debug kode, sebenarnya saya tidak dapat menemukan n * 2
transformasinya.
Adakah cara untuk melihat transformasi ini atau cara untuk men-debug kode ini dengan mudah?
EDIT: Saya telah menambahkan jawaban dari komentar yang berbeda dan jawaban diposting
Berkat Holger
komentar yang menjawab pertanyaan saya, pendekatan memiliki blok lambda memungkinkan saya untuk melihat proses transformasi dan men-debug apa yang terjadi di dalam tubuh lambda:
.map(
n -> {
Integer nr = n * 2;
return nr;
}
)
Berkat Stuart Marks
pendekatan memiliki referensi metode juga memungkinkan saya untuk men-debug proses transformasi:
static int timesTwo(int n) {
Integer result = n * 2;
return result;
}
...
List<Integer> result2 = naturals.stream()
.map(Java8Test::timesTwo)
.collect(Collectors.toList());
...
Berkat Marlon Bernardes
jawaban saya perhatikan bahwa Eclipse saya tidak menunjukkan apa yang seharusnya dan penggunaan peek () membantu menampilkan hasil.
result
variabel sementara Anda sebagaiInteger
. Yang sederhanaint
harus dilakukan juga jika Anda melakukanmap
pingint
keint
...Jawaban:
Saya biasanya tidak memiliki masalah debugging ekspresi lambda saat menggunakan Eclipse atau IntelliJ IDEA. Cukup tetapkan breakpoint dan pastikan untuk tidak memeriksa seluruh ekspresi lambda (hanya memeriksa isi lambda).
Pendekatan lain yang digunakan
peek
untuk memeriksa elemen aliran:MEMPERBARUI:
Saya pikir Anda semakin bingung karena
map
merupakanintermediate operation
- dengan kata lain: ini adalah operasi malas yang akan dijalankan hanya setelahterminal operation
dieksekusi. Jadi saat Anda memanggilstream.map(n -> n * 2)
tubuh lambda tidak sedang dijalankan saat ini. Anda perlu menyetel breakpoint dan memeriksanya setelah operasi terminal dipanggil (collect
, dalam kasus ini).Periksa Operasi Stream untuk penjelasan lebih lanjut.
UPDATE 2:
Mengutip komentar Holger :
sumber
inspect
dandisplay
dan mendapatkann cannot be resolved to a variable
. Btw, intip juga berguna tetapi mencetak semua nilai sekaligus. Saya ingin melihat setiap proses iterasi untuk memeriksa transformasi. Apakah itu memungkinkan?.map
baris dan tekan F8 beberapa kali.map
dan ekspresi lambda berada dalam satu baris sehingga titik henti sementara baris akan berhenti pada dua tindakan yang sama sekali tidak terkait. Memasukkan jeda baris tepat setelahnyamap(
akan memungkinkan Anda menetapkan titik henti hanya untuk ekspresi lambda. Dan bukan hal yang aneh jika debugger tidak menampilkan nilai perantara dari sebuahreturn
pernyataan. Mengubah lambda menjadin -> { int result=n * 2; return result; }
akan memungkinkan Anda untuk memeriksanyaresult
. Sekali lagi, sisipkan jeda baris dengan tepat saat melangkah baris demi baris…IntelliJ memiliki plugin yang bagus untuk kasus ini seperti plugin Java Stream Debugger . Anda harus memeriksanya: https://plugins.jetbrains.com/plugin/9696-java-stream-debugger?platform=hootsuite
Ini memperluas jendela alat Debugger IDEA dengan menambahkan tombol Trace Current Stream Chain, yang menjadi aktif ketika debugger berhenti di dalam rangkaian panggilan API Stream.
Ini memiliki antarmuka yang bagus untuk bekerja dengan operasi aliran terpisah dan memberi Anda kesempatan untuk mengikuti beberapa nilai yang harus Anda debug.
Anda dapat meluncurkannya secara manual dari jendela Debug dengan mengklik di sini:
sumber
Debugging lambda juga bekerja dengan baik dengan NetBeans. Saya menggunakan NetBeans 8 dan JDK 8u5.
Jika Anda menyetel breakpoint pada baris di mana terdapat lambda, Anda sebenarnya akan menekan sekali saat pipeline disiapkan, lalu sekali untuk setiap elemen aliran. Menggunakan contoh Anda, pertama kali Anda mencapai breakpoint adalah
map()
panggilan yang menyiapkan pipeline streaming:Anda dapat melihat tumpukan panggilan dan variabel lokal serta nilai parameter
main
seperti yang Anda harapkan. Jika Anda terus melangkah, breakpoint yang "sama" dipukul lagi, kecuali kali ini dalam panggilan ke lambda:Perhatikan bahwa kali ini tumpukan panggilan berada jauh di dalam mesin aliran, dan variabel lokalnya adalah lokal lambda itu sendiri, bukan
main
metode pelingkupan . (Saya telah mengubah nilai dalamnaturals
daftar untuk memperjelas ini.)Seperti yang ditunjukkan oleh Marlon Bernardes (+1), Anda dapat menggunakan
peek
untuk memeriksa nilai saat nilai berjalan di dalam pipeline. Berhati-hatilah jika Anda menggunakan ini dari aliran paralel. Nilainya dapat dicetak dalam urutan tak terduga di berbagai utas. Jika Anda menyimpan nilai dalam struktur data debugging daripeek
, struktur data tersebut tentu saja harus aman untuk thread.Terakhir, jika Anda melakukan banyak debugging lambda (terutama lambda pernyataan multi-baris), mungkin lebih baik untuk mengekstrak lambda ke dalam metode bernama dan kemudian merujuknya menggunakan referensi metode. Sebagai contoh,
Ini mungkin mempermudah untuk melihat apa yang terjadi saat Anda melakukan debug. Selain itu, mengekstraksi metode dengan cara ini mempermudah pengujian unit. Jika lambda Anda sangat rumit sehingga Anda harus melewatinya satu langkah, Anda mungkin ingin melakukan banyak pengujian unit untuk itu.
sumber
{ int result=n * 2; return result; }
baris yang berbeda dan saya dapat menerima jawabannya karena kedua jawaban itu membantu. +1 tentu saja.Intellij IDEA 15 tampaknya membuatnya lebih mudah, memungkinkan untuk berhenti di bagian garis di mana lambda berada, lihat fitur pertama: http://blog.jetbrains.com/idea/2015/06/intellij-idea-15 -eap-is-open /
sumber
Hanya untuk memberikan detail yang lebih baru (Okt 2019), IntelliJ telah menambahkan integrasi yang cukup bagus untuk men-debug jenis kode yang sangat berguna ini.
Ketika kita berhenti di baris yang berisi lambda jika kita menekan F7(melangkah ke) maka IntelliJ akan menyorot apa yang akan menjadi potongan untuk debug. Kita dapat mengganti potongan apa yang akan didebug Tabdan setelah kita memutuskannya maka kita klik F7lagi.
Berikut beberapa tangkapan layar untuk diilustrasikan:
1- Tekan F7(melangkah ke), akan menampilkan sorotan (atau mode pemilihan)
2- Gunakan Tabbeberapa kali untuk memilih potongan yang akan di-debug
3- Tekan F7tombol (melangkah ke) untuk masuk
sumber
Debugging menggunakan IDE selalu membantu, tetapi cara ideal untuk men-debug melalui setiap elemen dalam aliran adalah dengan menggunakan peek () sebelum operasi metode terminal karena Java Steams dievaluasi secara malas, jadi kecuali metode terminal dipanggil, aliran masing-masing akan tidak dievaluasi.
sumber