Java面接問題の簡単な解答問題(一)

15349 ワード

Java面接問題の簡単な解答問題(一)


タイトルが高いと発表されたSimpleDateFormat


テーマの内容

 , :

public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");

public static String formatDate(Date date) {
  return dateFormat.format(date);
}

 ? .

テーマ解析


高同時性の場合、複数のスレッドがformatDateメソッドを呼び出し、NumberFormatExceptionという異常が発生する可能性があります.次のコードを使用してテストします.
 private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        public static void main(String[] args) throws InterruptedException {
            ExecutorService executorService = Executors.newFixedThreadPool(500);
            for (int i = 0; i < 500; i++) {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 1000000; i++) {
                            try {
                                DATE_FORMAT.parse("2018-09-04 00:00:00");
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }
            Thread.sleep(3000000);
        }

エラー:
java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Long.parseLong(Long.java:601)
    at java.lang.Long.parseLong(Long.java:631)
    at java.text.DigitList.getLong(DigitList.java:195)
    at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
    at java.text.DateFormat.parse(DateFormat.java:364)
    at cn.love.potion.test.DateTest$1.run(DateTest.java:41)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

この問題が一般的な原因は , ,であるが、私たちのソースコードで伝達された過去の日付フォーマットは正しい.SimpleDateFormatクラスのソースコードに入ると、次の注記が表示されます(jdk 1.8ベース).
大まかに訳すと、
date formatsは同期していません.スレッドごとに個別のインスタンスを作成することを推奨します.複数のスレッドがformatメソッドに同時にアクセスする場合は、追加の同期が必要です.
具体的なエラーの発生を知りたい場合は、SimpleDateFormatクラスのソースコードを見て、ここではあまり紹介しません.もし分からないならば下で私に伝言をあげることができて、私はこの解析を書き直します.従来の解決策は、synchronizedを用いる方法にロックをかけることであり、性能の問題にあまりこだわる必要はない、 .

タイトル2 LinkedListでのエラー操作


テーマの内容

 LinkedList list, [1....100000] (10w), 10000 , ?
for(int i = 90000; i<list.size(); i++){
    System.out.println(list.get(i));
}

テーマ解析


LinkedListのデータ構造は双方向チェーンテーブルに基づいていることはよく知られており、getメソッドを使用すると、まず検索要素のインデックスが1/2 sizeより大きいかどうかを判断する.より大きい場合は、最後の要素から前方へのクエリーを開始します.そうでない場合は、最初の要素から後方へのクエリーを開始します.
 if (index < (size >> 1)) {
            Node x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }

解決策

get は、getメソッドを使用して大量の連続LinkedListデータを取得することを推奨せず、反復器または強化forループ(本質は反復器)を使用することを推奨する.この問題では、LinkedListが持参する以下の方法を使用することができる.
ListIterator iterator = list.listIterator(90000);
   while (iterator.hasNext()) {
       System.out.println(iterator.next());
   }

題目3空間複雑度o(1)でのArrayListからの偶数項の除去


テーマの内容

 , , ?
 public void removeElement(){
        List<Integer> list = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 1000; i++) {
            list.add(random.nextInt(10000));
        }
        for (Integer i : list) {
            if (i % 2 == 0) {
                list.remove(i);
            }
        }
    }

テーマ解析


ArrayListは、クラスで定義1つの変数modCountに基づいて実現されるfail-fastメカニズムである、ArrayListオブジェクトを添削するたびにmodCount++という動作が行われる.ArrayListオブジェクトを巡回する場合、現在のオブジェクトの処理が完了するたびに、オブジェクトのmodCountが巡回開始時のmodCountと一致するか否かを比較し、一致しない場合はConcurrentModificationException、このタイトルの remove に報告する.だから間違いを報告します.

解決策


ArrayListクラスには反復器が提供するており、それが持参した反復器を用いて遍歴除去すればエラーは発生しない.コードは次のとおりです.

  Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer i = iterator.next();
            if (i % 2 == 0) {
                // , 
                iterator.remove();
            }
        }

タイトル4文字列の"=="と"equals"


テーマの内容

 

String s1 = "hello";
String s2 = "hell";
String s3 = s2 + "o";
if (s1 == s3) {
    System.out.println("A");
} else if (s1.equals(s3)) {
    System.out.println("B");
}

テーマ解析


この問題の重要なポイントは、文字列の作成と破棄プロセスを理解することであり、String s1 = "hello"という方法で文字列を作成すると、まず定数プールにこの文字列が存在するかどうかを探し、存在しない場合は定数プールに対象を作成し、スタック内の参照をこのオブジェクトに向ける.このトピックでは、String s3 = s2 + "o";を行うと、まず定数プールに「hello」オブジェクトが存在するかどうかを見る、存在しない場合は定数プールにオブジェクトを作成し、スタックにオブジェクトを再作成し、スタック内の参照をスタック内のこのオブジェクトに向ける.したがって、本タイトルでは、==を用いる比較を行う場合、s 1とs 3のメモリアドレスが異なる(定数プール内のオブジェクトを指す、スタック内のオブジェクトを指す)ため、s1==s3という条件が満たされず、Stringクラスがequalsメソッドを書き換えたため、文字列のアドレスが同じかどうかではなく文字列の内容が同じか否かを比較するので、s1.equals(s3)が成立し、Bを印刷する.

題目5 final修飾変数の不変性


テーマの内容

 , ?
public int addOne(final int x) {
  return x++;
}

テーマ解析


変数をfinalに設定すると、この変数が参照する不変性は、基本タイプとそのパッケージタイプに対して、ベースタイプのパッケージタイプに対して、毎回++.-操作はいずれもオブジェクトを再作成し、新しく作成するオブジェクトを参照します.ベースタイプはメモリが指すオブジェクトの不変性として直接理解できます.したがって、この問題では、x++の操作はどうしても実行できない.

テーマ拡張


次のようなプログラムがある場合、コード実行に問題が発生しますか?
public class FinalTest {

  public static void main(String[] args) {
  FinalTest finalTest = new FinalTest();
  Other other = new Other();
  finalTest.add(other);
  }

  private void add(final Other other) {
  other.i++;
  }

}
class Other{
  public int i = 0;
}
:問題は発生しません.前にも述べたように、finalは参照の可変性を保証しています.otherオブジェクトのアドレスが変わらない限り、otherオブジェクトに対して他の操作を行うことはできます.finalは本当のimmutableを実現できません.(未完待機.....)
私のブログと公衆番号に注目してください.ブログを書き始めたばかりで、これからもっとよくなることを望んでいます.