日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】深入剖析Java输入输出的那些细节

發布時間:2025/3/15 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】深入剖析Java输入输出的那些细节 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

無論是新手入門的命令行輸入輸出,還是說OJ的讀入和輸出,離不開基本的IO操作。
但Java本身由于純粹的面向對象,輸入輸出不方便,所以我們倒不妨探討一番。

其實輸入輸出真實是所有學Java的入門者一定要先去學的,但用的越多越能深入地感受到輸入輸出或多或少的小問題。正所謂“養兵千日,用兵一時”,想要關鍵時刻一針見血,就必須在平時做好準備。

Are you ready? OK ~ 那今天我們就來聊聊,我們如何用好Java的輸入輸出。

看看Python

這叫輸入:

n=input()

可以用eval()將輸入類型轉換成數值類型,用int()轉換成整數類型……
如下:

n=eval(input())

這叫輸出:

print(n)

看看C++

cin可以輸入:

cin>>n;

輸入還可以用scanf()效率更高

cout可以輸出:

cout<<n;

輸出還可以用printf()效率更高

Java輸出篇

為什么先談輸出呢?
顯然因為簡單啊。

普通輸出流三種輸出方式:

第一種是不換行輸出

int n = 1; System.out.print(n);

第二種是換行輸出

System.out.println(n);

第三種是格式化輸出

System.out.printf("%d", n);

還有錯誤輸出流,與上述內容類似:

第一種是不換行輸出

System.err.print(n);

第二種是換行輸出

System.err.println(n);

第三種是格式化輸出

System.err.printf("%d", n);

Java輸出的一些問題

  • printf();如果格式化不正確,就會爆java.util.IllegalFormatConversionException異常。
  • 為什么Eclipse/IDEA這樣的IDE在爆異常的時候都可能紅字和普通字混合?
    異常是err錯誤流,普通輸出是out普通輸出流,可能會在IDE里由于線程的問題而混合在一起。
  • System.in/System.out/System.err是什么?
    根據下面的源碼(java.lang.System),可知分別是InputStream、PrintStream對象,err流和out流是同一個類的不同對象。 public static final InputStream in;public static final PrintStream out;public static final PrintStream err;`
  • 打印輸出的時候會啟動IO,所以不建議直接輸出,可以用StringBuilder把答案“組織好”再統一輸出。
  • 循環里每次都cout的時候能不輸出最后的空格,不需要額外的調整,但System.out.println()輸出的時候沒有這種考慮,必須自己處理最后一次的結果。我建議可以用builder.append(i).append(" ");和builder.toString().trim();,最后消去末尾的一個空格,即可完成所需要的輸出。
  • 格式化打印指定位數小數是常見操作,可用printf()完成任務目標。比如,System.out.printf("%.5f");就是保留五位小數打印浮點數。
  • ……(留待補充)
  • 對于第五條,說明一下。我們先寫一個測試類,打一下時間戳:

    public class PrintTest {public static void main(String[] args) {int[] array = new int[100000];long time1 = System.currentTimeMillis();for (int i = 0; i < array.length-1; i++) {System.out.print(array[i] + " ");}System.out.println(array[array.length-1]);long time2 = System.currentTimeMillis();StringBuilder builder = new StringBuilder();for (int i = 0; i < array.length; i++) {builder.append(array[i]).append(" ");}System.out.println(builder.toString().trim());long time3 = System.currentTimeMillis();System.out.println("策略1的輸出時間:" + (time2-time1));System.out.println("策略2的輸出時間:" + (time3-time2));} }

    除去上面的兩行輸出,會打印:
    策略1的輸出時間:330
    策略2的輸出時間:10

    顯然,用StringBuilder而不是直接一次接一次的System.out.print(),是正解啦。

    Java輸入篇

    記得在學校剛學的時候,第一節課老師就讓大家寫一下輸入輸出語句,輸出還好,輸入就不行了,很多同學不會寫。其實我也是在學了很多語法以后才學會的輸入啦,下面就來說一說吧。

    其實對初學者的一個困難就是輸出可以不必import,但輸入則不然,需要import java.io.*,或者import java.util.Scanner,可能不那么容易直接理解。

    一般比較“出名”的處理方式是java.util.Scanner,這倒確實。
    Scanner類可以直接讀取一下類型的對象:

    • public String next() → 讀取下一個字符串(默認分隔符為Space or Tab or Enter)
    • public String next?(String pattern) → 讀取下一個字符串(匹配到的串符合指定的正則表達式)
    • public String next?(Pattern pattern) → 讀取下一個字符串(匹配到的串符合指定的正則表達式)
    • public BigDecimal nextBigDecimal() → 讀取下一個高精小數(默認十進制)
    • public BigInteger nextBigInteger() → 讀取下一個高精整數(默認十進制)
    • public BigInteger nextBigInteger?(int radix) → 讀取下一個高精整數(指定進制)
    • public boolean nextBoolean() → 讀取下一個布爾值
    • public byte nextByte() → 讀取下一個byte整型數值(超容會報錯,默認十進制)
    • public byte nextByte?(int radix) → 讀取下一個byte整型數值(超容會報錯,指定進制)
    • public double nextDouble() → 讀取下一個雙精度浮點數值(默認十進制)
    • public float nextFloat() → 讀取下一個單精度浮點數值(默認十進制)
    • public int nextInt() → 讀取下一個int整型數值(超容會報錯,默認十進制)
    • public int nextInt?(int radix) → 讀取下一個int整型數值(超容會報錯,指定進制)
    • public String nextLine() → 讀取下一行內容以字符串類型返回(分隔符為Enter)
    • public long nextLong() → 讀取下一個long整型數值(超容會報錯,默認十進制)
    • public long nextLong?(int radix) → 讀取下一個long整型數值(超容會報錯,指定進制)
    • public short nextShort() → 讀取下一個short整型數值(超容會報錯,默認十進制)
    • public short nextShort?(int radix) → 讀取下一個short整型數值(超容會報錯,指定進制)

    看吧,確實“全能”,不過我們在看到Scanner便捷的同時也應該清醒地認識到其性能的低下。
    Scanner之所以能如此全能,依賴于Java支持的正則表達式,這點可以自行閱讀文檔或者源碼了解,這里不加詳細說明。
    我們試想,比如一行這樣的數據:
    1 2 555 333333 99 243 ……
    如果說每一次都用scanner.nextInt(),就會慢太多。
    反反復復的IO操作,每次都要判斷和處理,很影響效率的。

    比如說在洛谷刷算法題的時候,我一般是用Java,但很多次都被卡死性能,不管怎么優化也不行,最后發現問題就在Scanner身上,那怎么處理呢?

    答案是換BufferedReader,性能大幅提升。

    看下面的代碼:

    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); int num = Integer.parseInt(reader.readLine()); int[] record = new int[num]; String[] nums = reader.readLine().split("\\s+"); for (int i = 0; i < num; i++) {record[i] = Integer.parseInt(nums[i]); } reader.close();

    這樣一段代碼就可以先讀一個數值,再讀剩下一行里大量的數值。
    看似還要開一個String[],但其實都說過了,再慢也慢不過IO,希望大家心里清楚最慢的就是IO了,減少IO是提升性能之道。

    不過,在極其苛刻的情況下,Java是沒辦法完成的,嚴重TLE+MLE,哪怕你用了byte這樣的也不行,所以就得換C++了。畢竟算法題沒必要為Java設計性能指標,不達標也只能認了,Java比起C/C++太慢了。

    Java輸入的一些問題

  • 性能實在不達標,看不對就換BufferedReader,再不行就換C++。
  • 切記scanner.nextInt()之后沒換行,此時如果讀一行scanner.nextLine()可能只讀到空字符串——"",導致后續崩盤。所以遇到單行單個數值+單行多數值的情況,就直接先用Integer.parseInt(scanner.nextLine());再用String[] array = scanner.nextLine().split("\s+");,把String[]轉成int[]即可(切記不可直接強轉,二者毫無關系)。
  • IO真的是最慢的,千萬別多次IO。寧可處理麻煩點也別貪圖省代碼。
  • 使用完輸入流后記得關閉,這是一個好習慣。用scanner,就寫scanner.close(); ,用reader,就寫reader.close();。
  • 輸入流關閉之后就不能再用了,這點要注意,在最后用完之后關閉就好。
  • java.util.Scanner不需要處理異常,java.io.BufferedReader需要處理java.io.IOException,要么try…catch…finally,要么throws,不處理是不能通過編譯的。當然啦,自動關閉資源的try語句也挺好的。
  • ……
  • 總結

    以上是生活随笔為你收集整理的【Java】深入剖析Java输入输出的那些细节的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。