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; } } } }