Rumah  >  Artikel  >  Java  >  Bagaimana untuk menggunakan fungsi untuk melintasi tatasusunan dua dimensi di Jawa?

Bagaimana untuk menggunakan fungsi untuk melintasi tatasusunan dua dimensi di Jawa?

WBOY
WBOYke hadapan
2023-05-07 19:34:061124semak imbas

Pendahuluan

Bagi traversal tatasusunan, pada asasnya setiap pembangun telah menulis tentangnya Tidak banyak yang boleh dikatakan tentang traversal itu sendiri, tetapi apabila kita mempunyai beberapa logik perniagaan yang rumit semasa proses traversal, kita akan dapati. bahawa Tahap kod akan beransur-ansur mendalam

Sebagai contoh, dalam kes mudah, cari nombor genap dalam tatasusunan dua dimensi dan simpannya dalam senarai

Lintas dua dimensi tatasusunan dan nilai setiap elemen Sama ada nombor genap boleh ditulis dengan mudah, seperti:

public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    for (int i = 0; i < cells.length; i ++) {
        for (int j = 0; j < cells[0].length; j++) {
            if ((cells[i][j] & 1) == 0) {
                ans.add(cells[i][j]);
            }
        }
    }
    System.out.println(ans);
}

Tiada masalah dengan pelaksanaan di atas, tetapi kedalaman kod ini dengan mudah boleh tiga tahap; apabila dalam keadaan di atas jika terdapat syarat pertimbangan lain, maka tahap kod boleh ditingkatkan dengan mudah, tetapi jika ia adalah tatasusunan tiga dimensi, satu traversal akan menjadi tiga tahap; sedikit logik, empat atau lima tahap boleh dicapai dalam beberapa minit, bukan?

Selagi kod boleh dijalankan, apa masalahnya? !

1. Kaedah fungsi mengurangkan tahap kod

Memandangkan tahap traversal tatasusunan berbilang dimensi secara semula jadi sangat dalam, adakah terdapat cara untuk mengurangkannya?

Untuk menyelesaikan masalah ini, kuncinya ialah memahami perkara penting. Dapatkan koordinat setiap elemen! Jadi apa yang boleh kita lakukan?

Tentukan kaedah fungsi, input ialah koordinat fungsi, dan laksanakan logik traversal kami dalam badan fungsi ini

Berdasarkan idea di atas, saya percaya kita boleh dengan mudah Ia adalah mudah untuk menulis kaedah umum traversal tatasusunan dua dimensi
public static void scan(int maxX, int maxY, BiConsumer<Integer, Integer> consumer) {
    for (int i = 0; i < maxX; i++) {
        for (int j = 0; j < maxY; j++) {
            consumer.accept(i, j);
        }
    }
}

Terutamanya melaksanakan kaedah di atas secara langsung menggunakan BiConsumer yang disediakan oleh JDK secara lalai Kedua-dua parameter yang diluluskan adalah tatasusunan int seperti yang ditunjukkan dalam jadual di bawah; tiada nilai pulangan

Jadi bagaimana untuk menggunakan perkara di atas?

Begitu juga dengan contoh di atas setelah diubah, ia kelihatan seperti:

public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    scan(cells.length, cells[0].length, (i, j) -> {
        if ((cells[i][j] & 1) == 0) {
            ans.add(cells[i][j]);
        }
    });
    System.out.println(ans);
}
Berbanding dengan yang sebelumnya, nampaknya hanya ada satu lapisan sahaja yang hilang. dan ia nampaknya bukan sesuatu yang istimewa

Walau bagaimanapun, apabila tatasusunan menjadi tiga dimensi, empat dimensi atau bukan dimensi, tahap penulisan perubahan ini tidak akan berubah

2. Kembali semasa traversal supports

front Tiada masalah dengan pelaksanaan traversal biasa tetapi apabila kita menghadapi keadaan tertentu semasa proses traversal dan kembali secara langsung, bolehkah ia disokong?

Sebagai contoh, jika kita melintasi tatasusunan dua dimensi dan kita ingin menentukan sama ada terdapat nombor genap di dalamnya, bagaimanakah kita boleh membundarkannya?

Fikirkan kaedah imbasan kami dengan teliti dan harap ia boleh menyokong pengembalian Masalah utama ialah selepas kaedah fungsi ini dilaksanakan, bagaimana saya tahu sama ada untuk meneruskan gelung atau kembali secara langsung mudah Apa yang terlintas di fikiran ialah menambah nilai pulangan tambahan pada logik pelaksanaan untuk menandakan sama ada untuk mengganggu gelung dan kembali secara langsung

Berdasarkan idea ini, kami boleh melaksanakan versi demo ringkas

untuk mentakrifkan kaedah fungsi , menerima subskrip gelung + nilai pulangan

@FunctionalInterface
public interface ScanProcess<T> {
    ImmutablePair<Boolean, T> accept(int i, int j);
}

Kaedah umum gelung boleh diubah sewajarnya:

public static <T> T scanReturn(int x, int y, ScanProcess<T> func) {
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            ImmutablePair<Boolean, T> ans = func.accept(i, j);
            if (ans != null && ans.left) {
                return ans.right;
            }
        }
    }
    return null;
}

Berdasarkan idea di atas, kami Postur penggunaan sebenar adalah seperti berikut:

@Test
public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    List<Integer> ans = new ArrayList<>();
    scanReturn(cells.length, cells[0].length, (i, j) -> {
        if ((cells[i][j] & 1) == 0) {
            return ImmutablePair.of(true, i + "_" + j);
        }
        return ImmutablePair.of(false, null);
    });
    System.out.println(ans);
}

Pelaksanaan di atas dapat memenuhi keperluan kami. ada cara lain? Sekarang nilai pulangan telah dipertimbangkan, bagaimana pula dengan lulus parameter? Adakah boleh menggunakan parameter yang ditentukan untuk menentukan sama ada untuk mengganggu dan mengembalikan hasilnya?

Berdasarkan idea ini, kita boleh mentakrifkan kelas pembungkusan parameter dahulu:

public static class Ans<T> {
    private T ans;
    private boolean tag = false;

    public Ans<T> setAns(T ans) {
        tag = true;
        this.ans = ans;
        return this;
    }

    public T getAns() {
        return ans;
    }
}

public interface ScanFunc<T> {
    void accept(int i, int j, Ans<T> ans)
}

Kami berharap dapat merekodkan hasil gelung melalui kelas Ans, di mana tag=true bermaksud Tidak perlu meneruskan gelung, hanya kembalikan hasil jawapan terus

Pengubahsuaian kaedah dan contoh yang sepadan adalah seperti berikut:

public static <T> T scanReturn(int x, int y, ScanFunc<T> func) {
    Ans<T> ans = new Ans<>();
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            func.accept(i, j, ans);
            if (ans.tag) {
                return ans.ans;
            }
        }
    }
    return null;
}
public void getEven() {
    int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}};
    String ans = scanReturn(cells.length, cells[0].length, (i, j, a) -> {
        if ((cells[i][j] & 1) == 0) {
            a.setAns(i + "_" + j);
        }
    });
    System.out.println(ans);
}

Dengan cara ini ia kelihatan lebih baik daripada yang sebelumnya

Sebenarnya jalankan untuk melihat sama ada output adalah konsisten dengan jangkaan kami;

Atas ialah kandungan terperinci Bagaimana untuk menggunakan fungsi untuk melintasi tatasusunan dua dimensi di Jawa?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam