JDK6 to JDK7 => API Enhancements

Description

打算把系統的執行環境從 JDK6 升級到 JDK7, 整理一下有哪些可用.
比較期待的部分是語法, NIO2, G1. 這頁是整理語法的部分.

Reference

Points

  1. Strings in switch Statements
    package test;
    
    public class TestStringSwitch {
    
     public static void main(String[] params) {
      inJDK7("abc");
      inJDK6("abc");
     }
     
     private static void inJDK7(String txt) {
      switch (txt) {
      case "a":
       System.out.println("a");
       break;
      case "b":
       System.out.println("b");
       break;
      case "abc":
       System.out.println("abc");
       break;
      default:
        System.out.println("not match");
      }
     }
     
     private static void inJDK6(String txt) {
      if ( "a".equals(txt) ) {
       System.out.println("a");
      } else if ( "b".equals(txt) ) {
       System.out.println("b");
      } else if ( "abc".equals(txt) ) {
       System.out.println("abc");
      } else {
       System.out.println("not match");
      }
     }
     
     
    }
    
  2. Type Inference for Generic Instance Creation
    package test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class TestGenericDeclare {
    
      public static void main(String[] params) {
        // JDK6
        Map> map0 = new HashMap>();
        
        // JDK7
        Map> map1 = new HashMap<>();
      }
      
    }
    
  3. The try-with-resources Statement
    試用後可以看到這個語法可以讓程式簡化很多.
    package test;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    
    public class TestAutoClosable {
    
        public static void main(String[] params) throws IOException {
            File file1 = new File("d:/test.txt");
            File file2 = new File("d:/test2.txt");
            inJDK6(file1,file2);
            inJDK7(file1,file2);
        }
    
        private static void inJDK7(File file1, File file2) throws IOException {
            try (
                FileReader fileReader1 = new FileReader(file1);
                FileReader fileReader2 = new FileReader(file2);
                BufferedReader reader1 = new MyBufferedReader("7 reader1", fileReader1);
                BufferedReader reader2 = new MyBufferedReader("7 reader2", fileReader2);
            ) {
                System.out.println(reader1.readLine());
                System.out.println(reader2.readLine());
            }
        }
        
        private static void inJDK6(File file1, File file2) {
            BufferedReader reader1 = null;
            BufferedReader reader2 = null;
            try {
                reader1 = new MyBufferedReader("JDK6 style reader1", new FileReader(file1));
                reader2 = new MyBufferedReader("JDK6 style reader2", new FileReader(file2));
                System.out.println(reader1.readLine());
                System.out.println(reader2.readLine());
            } catch(Throwable ex) {
                ex.printStackTrace();
            } finally {
                if ( reader1 != null ) {
                    try {
                        reader1.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if ( reader2 != null ) {
                    try {
                        reader2.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        
        private static class MyBufferedReader extends BufferedReader {
            private final String name;
            public MyBufferedReader(String name, Reader reader) {
                super(reader);
                this.name = name;
            }
            @Override
            public void close() throws IOException {
                super.close();
                System.out.println("close " + name);
            }
        }
        
    }
    
  4. Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
    有時對於不特別處理的 checked exception 動作也只是往外丟, 在 JDK7 之前需要在 method 上特別註明這個 checked exception, 但 JDK7 之後, 沒有特別需要的, 直接往外丟的 exception 就算沒有在 method 上宣告, compiler 也不會判你錯.
    package test;
    
    public class TestHandleMoreThanOneException {
    
        public static void main(String[] params) throws Exception {
            rethrowEx("3");
        }
    
        private static void rethrowEx(String exNum) throws Ex1,Ex2 {
            try {
                throwEx(exNum);
            } catch (Ex1 | Ex2 e) {
                throw e;
            } catch (Exception e) {
                throw e;
            }
        }
        
        private static void throwEx(String exNum) throws Ex1, Ex2 {
            switch (exNum) {
            case "1":
                throw new Ex1();
            case "2":
                throw new Ex2();
            default:
                System.out.println("not match");
            }
        }
        
        public static class Ex1 extends Exception {}
        public static class Ex2 extends Exception {}
        
    }
    


python 處理 json

Description

現在很常用 json 當成儲存資料的格式, 用 java 的話需要導入 library.
python 則是內建 json 的 module, 只要操作原生的資料結構就行了. 很方便.

Reference

Codes

>>> import json
>>> m = {'a':1,'b':[1,2,3,4,5,6]}
>>> with open('d:/test.txt','w') as f:
        json.dump(m,f)

        
>>> with open('d:/test.txt') as f:
        f.readline()

        
'{"a": 1, "b": [1, 2, 3, 4, 5, 6]}'
>>> with open('d:/test.txt') as f:
        x = json.load(f)

        
>>> x
{'a': 1, 'b': [1, 2, 3, 4, 5, 6]}
>>> 

File content

{"a": 1, "b": [1, 2, 3, 4, 5, 6]}

python 的 main method

之前看 python 文章好像都沒提到怎麼寫 main method, 似乎這件事情很自然, 不過我卻不知道.
看了 6.1.1. Executing modules as scripts 裡面有寫
"the code in the module will be executed, just as if you imported it, but with the __name__ set to "__main__". That means that by adding this code at the end of your module:"
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))
試著作一次

  1. C:\Python33\say.py
    def say(words):
            print(words)
    
    if __name__ == '__main__':
            import sys
            say(sys.argv[1])
            print(__name__,sys.argv[0])
    
    
  2. Output
    C:\Python33>python.exe say.py hello
    hello
    __main__ say.py

這樣就可以了, 很簡單..

處理正在 iterate 的 dictionary


今天練習 Python 的時候發現 5.6. Looping Techniques 有個提示
"To change a sequence you are iterating over while inside the loop (for example to duplicate certain items), it is recommended that you first make a copy. Looping over a sequence does not implicitly make a copy."

照著文件上的程式輸入
>>> words = ['a','b','cc']
>>> for w in words:
    if len(w)>1:
        print('insert',w)
        words.insert(0,w)

執行之後就出現
insert cc
insert cc
insert cc
insert cc
insert cc
insert cc
insert cc
insertTraceback (most recent call last):
  File "<pyshell#208>", line 3, in <module>
    print('insert',w)
  File "C:\Python33\lib\idlelib\PyShell.py", line 1318, in write
    return self.shell.write(s, self.tags)
KeyboardInterrupt

要 Ctrl+C 才能停下來.
這時候檢查一下哪打錯了, 原來我打
for w in words:

但文件上是
for w in words[:]:

修正之後果然就正常了.
原來 words[:] 是 words 的 copy.
試一下
>>> words is words
True
>>> words is words[:]
False
果然沒錯.

在 Java 也是一樣, 如果要改變正在 iterate 的 list 也會有問題
package test;

import java.util.Arrays;
import java.util.List;

public class TestIter {

    public static void main(String[] params) {
        List words = Arrays.asList("a","b","cc");
        for (String w: words) {
            if (w.length() > 1) {
                System.out.println("insert " + w);
                words.add(w);
            }
        }
    }
    
}
會報錯
insert cc
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(Unknown Source)
    at java.util.AbstractList.add(Unknown Source)
    at test.TestIter.main(TestIter.java:13)

要改成
package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TestIter {

    public static void main(String[] params) {
        List words = Arrays.asList("a","b","cc");
        List copyWords = new ArrayList(words);
        for (String w: words) {
            if (w.length() > 1) {
                System.out.println("insert " + w);
                copyWords.add(0,w);
            }
        }
        System.out.println(words);
        System.out.println(copyWords);
    }
    
}

寫了 Python 跟 Java 這兩段程式, 感覺有微妙的差異...

巴斯卡三角形 in Python

Source Code

def print_pascal(row_cnt):
    pascal = []
    for row in range(row_cnt):
        cols = []
        for col in range(row+1):
            if row == 0:
                cols.append(1)
            elif col == 0 or col == row:
                cols.append(1)
            else:
                val = pascal[row-1][col-1]+pascal[row-1][col];
                cols.append(val)
        pascal.append(cols)
    for row in pascal:
        for i in range(row_cnt-len(row)):
            print('%5s' %'',end='')
        for col in row:
            print('%5d' %col,end='%5s' %'')
        print()

Usage


>>> print_pascal(6)
                             1     
                        1         1     
                   1         2         1     
              1         3         3         1     
         1         4         6         4         1     
    1         5        10        10         5         1  

別名演算法 Alias Method

 題目 每個伺服器支援不同的 TPM (transaction per minute) 當 request 來的時候, 系統需要馬上根據 TPM 的能力隨機找到一個適合的 server. 雖然稱為 "隨機", 但還是需要有 TPM 作為權重. 解法 別名演算法...