Pertimbangkan skenario pemrograman kompetitif, saya harus membaca 2*10^5 (atau Bahkan lebih banyak) angka dari console . Kemudian saya menggunakan BufferedReader atau bahkan untuk kinerja yang cepat saya menggunakan kelas pembaca khusus yang menggunakan DataInputStream di bawah tenda.

Pencarian Internet cepat memberi saya ini.

Kita dapat menggunakan java.io untuk streaming data yang lebih kecil dan untuk streaming yang besar dapat menggunakan java.nio.

Jadi saya ingin mencoba input konsol java.nio dan mengujinya terhadap kinerja java.io .

  1. Apakah mungkin membaca input konsol menggunakan java.nio ?
  2. Bisakah saya membaca data dari System.in menggunakan java.nio ?
  3. Apakah akan lebih cepat dari metode input yang saya miliki saat ini?

Setiap informasi yang relevan akan dihargai.

Terima kasih ️

1
Aashish Pawar 28 Mei 2020, 10:10

1 menjawab

Jawaban Terbaik

Anda dapat membuka saluran untuk stdin suka

FileInputStream stdin = new FileInputStream(FileDescriptor.in);
FileChannel stdinChannel = stdin.getChannel();

Ketika stdin telah dialihkan ke file, operasi seperti menanyakan ukuran, melakukan transfer cepat ke saluran lain dan bahkan pemetaan memori dapat bekerja. Tetapi ketika inputnya adalah konsol nyata atau pipa atau Anda sedang membaca data karakter, kinerjanya tidak mungkin berbeda secara signifikan.

Performanya tergantung pada cara Anda membacanya, bukan kelas yang Anda gunakan.

Contoh kode yang langsung beroperasi pada saluran, untuk memproses angka desimal yang dipisahkan spasi, adalah

CharsetDecoder cs = Charset.defaultCharset().newDecoder();
ByteBuffer bb = ByteBuffer.allocate(1024);
CharBuffer cb = CharBuffer.allocate(1024);
while(stdinChannel.read(bb) >= 0) {
    bb.flip();
    cs.decode(bb, cb, false);
    bb.compact();
    cb.flip();
    extractDoubles(cb);
    cb.compact();
}
bb.flip();
cs.decode(bb, cb, true);
if(cb.position() > 0) {
    cb.flip();
    extractDoubles(cb);
}
private static void extractDoubles(CharBuffer cb) {
    doubles: for(int p = cb.position(); p < cb.limit(); ) {
        while(p < cb.limit() && Character.isWhitespace(cb.get(p))) p++;
        cb.position(p);
        if(cb.hasRemaining()) {
            for(; p < cb.limit(); p++) {
                if(Character.isWhitespace(cb.get(p))) {
                    int oldLimit = cb.limit();
                    double d = Double.parseDouble(cb.limit(p).toString());
                    cb.limit(oldLimit);
                    processDouble(d);
                    continue doubles;
                }
            }
        }
    }
}

Ini lebih rumit daripada menggunakan java.util.Scanner atau BufferedReader's readLine() diikuti oleh split("\\s"), tetapi memiliki keuntungan menghindari kerumitan mesin regex, serta tidak membuat objek String untuk garis. Ketika ada lebih dari satu nomor per baris atau baris kosong, yaitu string baris tidak akan cocok dengan string angka, ini dapat menghemat overhead penyalinan intrinsik ke konstruksi string.

Kode ini masih menangani rangkaian karakter arbitrer. Saat Anda mengetahui rangkaian karakter yang diharapkan dan berbasis ASCII, gunakan transformasi ringan alih-alih CharsetDecoder, seperti yang ditunjukkan dalam jawaban ini , dapat memperoleh peningkatan kinerja tambahan.

3
Holger 28 Mei 2020, 10:05