面試題學習

   a left join b最多返回多少條記錄,最少返回多少條記錄?node

      a left join b將返回a中全部的記錄和b中符合on條件的記錄。mysql

      最少返回的記錄數是a的記錄數,這仍是好理解的。sql

      最多返回的記錄數a*b,以下:數組

      select * from a;多線程

      id   nameapp

      1    allenide

      2    tim測試

      3    jackson優化

      select * from b;this

      id    grade

      4    a

      5    b

      select a.id,a.name,b.grade from a left join b on a.id != b.id;返回的記錄數是6條。

 

  PreparedStatement和Statement的區別

      應儘可能使用PreparedStatement,能夠防止SQL注入,例如:      

  mysql> select * from a where name = "abc" or 1=1--"";

  +------+--------  +

  | id  | name  |

  +------+--------  +

  |    1 | allen |

  |    2 | edison |

  |    3 | tim  |

  +------+--------+

  3 rows in set (0.00 sec)

   name字段輸入的是:abc" or 1=1--",本應該查不到任何記錄,結果倒是查到了全部的記錄。

     使用PreparedStatement作測試,查詢到的結果是空,是不存在SQL注入的問題。PreparedStatement會先進行預編譯,傳遞的參數會被當作字符串進行處理,這樣就不會出現SQL拼接產生的問題。   

   String sql = "select * from a where name = ?";

   String paramter = "abc\" or 1=1--\"";

   Connection conn = null;

   PreparedStatement pstmt = null;

   ResultSet rs = null;

   try {

    conn = DBConnectionManager.getConnection();

    pstmt = conn.prepareStatement(sql);

    for (int i = 0; params != null && i < params.length; i++){

         pstmt.setString(i + 1, params[i]);

     }

        使用PreparedStatement還須要注意的一點是,在MySQL中,字段上若是有索引而且是varchar的,查詢時不加引號,會致使爲普通查詢,索引會失效。反之,字段上若是有索引而且是int的,查詢時加不加引號都是OK的。       

  mysql> explain select * from rcnetnode where index_in_mib = 10100001;

  +----+-------------+-----------+------+------------------+------+---------+------+------+-------------+

  | id | select_type | table     | type | possible_keys    | key  | key_len | ref  | rows | Extra       |

  +----+-------------+-----------+------+------------------+------+---------+------+------+-------------+

  |  1 | SIMPLE      | rcnetnode | ALL  | idx_index_in_mib | NULL | NULL    | NULL |  203 | Using where |

  +----+-------------+-----------+------+------------------+------+---------+------+------+-------------+

  1 row in set (0.00 sec)

 

  mysql> explain select * from rcnetnode where index_in_mib = "10100001";

  +----+-------------+-----------+------+------------------+------------------+---------+-------+------+-------------+

  | id | select_type | table     | type | possible_keys    | key              | key_len | ref   | rows | Extra       |

  +----+-------------+-----------+------+------------------+------------------+---------+-------+------+-------------+

  |  1 | SIMPLE      | rcnetnode | ref  | idx_index_in_mib | idx_index_in_mib | 203     | const |    2 | Using where |

  +----+-------------+-----------+------+------------------+------------------+---------+-------+------+-------------+

  1 row in set (0.00 sec)

      因此上面的代碼中pstmt.setString(i + 1, params[i]);是沒有問題的。

 

  HashMap實現的底層原理

      先從根源提及,對象的比較使用的是equals方法。比較字符串的內容用equals而不是==,是由於String類已經重寫了equals,比較的是字符串的內容,而不是Object的比較內存地址。

      對象的比較重寫equals方法的同時會重寫hashcode方法,這是由於對象若是要放到hash類的集合(hashmap,hashset)中時,hashcode是對key進行散列的依據,決定了散列的效率。

     

       從上圖咱們能夠發現HashMap是由數組+鏈表組成的,初始的容量是16,負載因子是0.75,即存儲的元素超過12個時,容量自動擴充爲32.元素存儲的位置是key%16,好比31,31%16結果是15,(15,value)就在15的位置。

       

       HashMap對於上述的過程作了一些優化,不單單是key%16了。

       當調用put(key,value)時,首先獲取key的hashcode,int hash = key.hashCode(); 
       再把hash經過一下運算獲得一個int h. 
       hash ^= (hash >>> 20) ^ (hash >>> 12); 
       int h = hash ^ (hash >>> 7) ^ (hash >>> 4);

       再作index = h & (length-1),算出的index是(key,value)應在的位置,這樣作會使index的分佈儘可能均勻。

       這點也是好理解的,若是hashcode寫的很差,簡單的key%16可能會使得個別鏈條很長,這樣效率是較低的。

       HashSet的實現是用的HashMap的key。

 

    多線程模擬多個客戶進行轉帳操做,有一個方法是轉帳,要求當轉出金額大於帳戶餘額時該線程放棄執行,將執行權力交給其餘的線程。

        第一個反應是用yield,可是yield依賴於操做系統,不是最好的選擇。

        正確的應是用notifyAll通知其餘線程去繼續執行,須要注意的是同步塊鎖得對象是this,下面是個例子程序。每一個線程打印5個數字,將執 行權力交給其餘的線程。

        使用notifyAll而不notify是由於notify更容易引發死鎖而notifyAll則不會。      

public class NotifyTest {
 public static void main(String[] args) {
  TestThread t = new TestThread();
  Thread t1 = new Thread(t);
  Thread t2 = new Thread(t);
  Thread t3 = new Thread(t);
  
  t1.start();
  t2.start();
  t3.start();
 }
}

class TestThread implements Runnable{
 int sum = 100;
 @Override
 public synchronized void run() {
  int localNum = sum;
  for(int i= sum;;){   
   if(i<= localNum -5){
    this.notifyAll();
    break;
   }else{
    System.out.println(Thread.currentThread().getName() + ":"+ i);
    i--;
    sum = i;
   }
  }  
 } 
}
相關文章
相關標籤/搜索