- Old Java
String[][] names = { { "John", "Mary", "Steven" }, { "Tom", "Jeff" } }; List<String> list1 = new ArrayList<String>(); for (String[] s1 : names) { for (String s2 : s1) { list1.add(s2); } }
- Java 8 Stream API
String[][] names = { { "John", "Mary", "Steven" }, { "Tom", "Jeff" } }; List<String> list2 = Arrays.stream(names) .flatMap(s1 -> Arrays.stream(s1)) .collect(Collectors.toList());
- C# LINQ (method syntax)
string[][] names = { new string[] { "John", "Mary", "Steven" }, new string[] { "Tom", "Jeff" } }; List<string> list3 = names.SelectMany(s1 => s1).ToList();
11/04/2014
8/26/2014
Docker
Docker 是一個開源的軟體容器(software containers), 利用 Linux kernel 中的隔離(isolation)特性, 實現了OS level virtualization
- 目前常見虛擬化技術類型(Virtualization Types)
- PV(paravirtualization), 透過修改OS核心,植入Hypercall,讓原本無法被虛擬化的指令,可以經過 Hyper interface 直接向硬體提出請求
http://en.wikipedia.org/wiki/Paravirtualization - HVM(hardware virtual machine)
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/virtualization_types.html - Application level virtualization - JVM, CLR
- OS level virtualization - docker
- PV(paravirtualization), 透過修改OS核心,植入Hypercall,讓原本無法被虛擬化的指令,可以經過 Hyper interface 直接向硬體提出請求
- Hypervisor 有兩種類型
- Type 1 (Bare-Metal hypervisor) - 又稱為 Native VM, hypervisor 直接安裝於機器上,直接掌控硬體資源,硬碟無須事先安裝OS,例如 VMware ESXi, 在 Xen 第一個建立 domain 稱之為 Dom0 它可以管理並且針對硬體做設定,還可以建立 DomU
- Type 2 (Hosted hypervisor)- 又稱為 Hosted VM,須先安裝 OS 才可使用,例如 VMware Player
- docker 優點
- 輕量級虛擬化:啟動 Container 速度快,Container 重新啟動後,回復原本乾淨的環境
- 自動建構:使用 Dockerfile 可自動建構環境
- 版本控制
- Docker hub
- docker 安裝 - Ubuntu 14.04, 可參考 http://docs.docker.com/installation/ubuntulinux/
$ sudo apt-get update $ sudo apt-get install docker.io $ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker $ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io
-
docker 指令
$ sudo docker pull centos (取得 image) $ sudo docker images (安裝的 image 列表) $ sudo docker run centos yum install redhat-lsb -y (安裝 redhat-lsb) $ sudo docker commit containerID newImgName (commit 成新的 image) $ sudo docker run newImgName lsb_release -d (顯示 linux 版本) $ sudo docker run ubuntu ifconfig (顯示 ip) $ sudo docker run -i -t ubuntu /bin/bash (互動模式) $ sudo docker ps (顯示正在 run 的 process) $ sudo docker ps -l <-- last $ sudo docker ps -a -s (-a makes sure you see already closed containers,-s gives you the container file size as well) $ sudo docker run -p 9999:8080 imgName command (port forwarding,前面是實體 linux 的 port,後面為 container 的 port) $ sudo docker run -d -p 9999:8080 imgName command (Daemonize) $ sudo docker run -d -p 27017:27017 -p 28017:28017 -v /path/to/data/db/:/data/db myhubpath/mongodb (mounts the current working directory into the container) $ sudo docker kill containerID (kill 正在 run 的 process)
- Dockerfile
$ sudo docker build –t imgName .
PLSQL Developer & SQL Navigator password 備份
- PLSQL Developer 儲存的 password 預設存在 C:\Users\[username]\AppData\Roaming\PLSQL Developer\Preferences\[username]\user.prefs
或安裝目錄下的 \PLSQL Developer\Preferences\[username]\user.prefs
自訂路徑 可修改安裝目錄下的 \PLSQL Developer\params.ini 並且定義 prefpath 參數
- SQL Navigator
password 儲存在 HKEY_CURRENT_USER\Software\Quest Software\SQL Navigator ?.?.?\Logon Passwords
6/17/2014
Named and Optional Arguments in C#, Python, JavaScript
C#
C# 在使用具名引數上非常方便, function 不需做任何修改即可使用
public double CalculateBMI(double height, double weight, bool isPrint = true) { double heightMeter = height / 100D;//double suffix double bmi = weight / Math.Pow(heightMeter, 2); //double bmi = Math.Floor(weight / Math.Pow(heightMeter, 2) * 100) / 100; if (isPrint) Console.WriteLine("BMI=" + bmi); return bmi; }
傳入參數的方式使用類似 JSON 的表示法, 且傳入不需有順序性
CalculateBMI(height: 170, weight: 65); CalculateBMI(height: 170, weight: 65, isPrint: false);
Python
具名引數和選擇性參數,在 Python 稱做 keyword arguments & default argument values,宣告 keyword arguments 必須在函式參數的變數前面加上兩顆星號,** 可以將引數收集在一個 dictionary 物件中, 使用上要留意傳入參數宣告的順序, 下面的例子如果寫成 def calculateBMI(**keywords, isPrint=True): 是不合法的, keyword arguments 必須放在函式參數宣告的最後面
import math def calculateBMI(isPrint=True, **keywords): heightMeter = keywords['height'] / 100 bmi = keywords['weight'] / math.pow(heightMeter, 2) #bmi = math.floor(keywords['weight'] / math.pow(heightMeter, 2) * 100) / 100 if isPrint: print('BMI=', bmi) return bmi calculateBMI(height = 170, weight = 65) calculateBMI(False, height = 170, weight = 65)
Python 星號的用途不僅止於此,在某些相反情況下,譬如說你要傳遞的參數已經是一個列表但要調用的函數卻接受分開一個個的參數值,這時需要將已有的列表分拆開來,Python 有提供簡便的方式處理這樣的情形, 詳細可參考Unpacking Argument Lists, Extended Iterable Unpacking
JavaScript
將多個參數集合而成一個 JavaScript 的物件當作參入傳入 function, 此種方式稱為 options hash
function calculateBMI(options, isPrint) { var isprt = typeof(isPrint) == 'undefined' ? true : isPrint; var opts = options || {}; var heightMeter = opts['height'] / 100; var bmi = opts['weight'] / Math.pow(heightMeter, 2); //var bmi = Math.floor(opts['weight'] / Math.pow(heightMeter, 2) * 100) / 100; if (isprt) console.log('BMI=' + bmi); return bmi; } calculateBMI({height:170, weight:65}) calculateBMI({height:170, weight:65}, false)
Variable-length Argument in Java, C#, Python
- Java
public int sum(int... nums) { //nums.getClass().getTypeName() -> int[] int total = 0; for (int num : nums ) total += num; return total; }
- C#
public int Sum(params int[] nums) { //nums.GetType() -> System.Int32[] int total = 0; for (int i = 0; i < nums.Length; i++) total += nums[i]; return total; }
- Python
def sum(*nums): #type(nums) -> <class 'tuple'> total = 0 for num in nums: total += num return total
5/27/2014
Apache Commons Logging 整合 java.util.logging
- 設定 commons logging 使用 java.util.logging
在應用程式的 classpath 中加入 commons-logging.properties 檔案
commons-logging.properties 內容如下,作用是要 commons.logging 使用 Jdk14Logger
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
若不使用 commons-logging.properties, commons logging 會先搜尋 classpath 中是否存在 log4J , 若存在 log4J 則優先使用 log4J, 若不存 log4J 才會使用 java.util.logging, 順序可參考 org.apache.commons.logging.LogSource
- 建立 java.util.logging 設定檔
建立設定檔 logging.properties, 檔名可自訂
handlers= java.util.logging.FileHandler .level= INFO java.util.logging.FileHandler.pattern = test_%g.log java.util.logging.FileHandler.encoding = UTF-8 java.util.logging.FileHandler.limit = 10000000 java.util.logging.FileHandler.count = 10 java.util.logging.FileHandler.append = true java.util.logging.SimpleFormatter.format = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
- file pattern 可使用百分比符號加入一些簡單規則, 可參考 Class FileHandler
- java.util.logging.SimpleFormatter.format = ...., Java 7 之後的版本才支援此選項
- 設定 java.util.logging 讀取設定檔
方法一
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.properties"); try { LogManager.getLogManager().readConfiguration(input); } catch (SecurityException | IOException e) { e.printStackTrace(); }
方法二
設定 system property, 或在啟動程式時加入參數example: java -Djava.util.logging.config.file=logging.properties
在不指定設定檔的狀況下, 預設會讀取 System.getProperty("java.home")/lib/logging.properties 檔案, 可參考 LogManager 文件
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TestLog { private static final Log log = LogFactory.getLog(TestLog.class); public static void main(String[] args) { log.debug("Debug Message"); log.info("Info Message"); log.warn("Warn Message"); log.error("Error Message"); log.fatal("Fatal Message"); } }Log LEVEL 定義比較表
Java Logging | Commons Logging |
---|---|
SEVERE | FATAL |
SEVERE | ERROR |
WARNING | WARN |
INFO | INFO |
CONFIG | |
FINE | DEBUG |
FINER | |
FINEST | TRACE |
5/22/2014
Java Type Erasure
Java 的泛型其實是在編譯器上做了手腳,Java 在編譯時期由編譯器幫我們做了型別轉換的檢查,當 compile 成 bytecode 後,我們使用工具觀察,可以發現我們在程式中所使用的泛型全都不見了,也因此程式在 run time 時是看不到泛型的影子,這種泛型的實現方式稱作 type erasure, 其優點是確保了相容性, 而 .NET 的泛型就不一樣了, .NET 的泛型是真正運行於 CLR 層上的功能, 也因此 Java 的泛型與 .NET 相比, Java 多了許多限制
舉個例子,假設我們要實做一個 List, 當索引值超出 List 長度時, 回傳傳入泛型型別的實例
C#
Java
舉個例子,假設我們要實做一個 List, 當索引值超出 List 長度時, 回傳傳入泛型型別的實例
C#
public class Animal { public override String ToString() { return this.GetType().Name; } } public class Cat : Animal {} public class Dog : Animal {} public class Monkey : Animal {} public class AnimalList<T> : List<T> where T : Animal { public new T this[int index] { get { if (index < this.Count) { return base[index]; } else { return Activator.CreateInstance<T>(); } } set { base[index] = value; } } } public static void Main(string[] args) { AnimalList<Animal> a = new AnimalList<Animal>() { new Cat(), new Dog(), new Monkey() }; for (int i = 0; i < 10; i++) { Console.WriteLine(a[i]); } }C# 可利用傳入的 T 型別, 利用 reflection 建立物件實例
Java
public class Animal { @Override public String toString() { return this.getClass().getSimpleName(); } } public class Cat extends Animal {} public class Dog extends Animal {} public class Monkey extends Animal {} public class AnimalList<T extends Animal> extends ArrayList<T> { private final Class<T> clazz; public AnimalList(Class<T> clazz) { this.clazz = clazz; } @Override public T get(int index) { T result = null; if (index < size()) { result = super.get(index); } else { try { result = this.clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } return result; } } public static void main(String[] args) { final AnimalList<Animal> a = new AnimalList<Animal>(Animal.class) {{ add(new Cat()); add(new Dog()); add(new Monkey()); }}; for (int i = 0; i < 10; i++) { System.out.println(a.get(i)); } }
因 type erasure 的原因, 造成 JVM 在執行時期, 無法利用傳入的 T 型別, 建立物件實例, 所以必須在 constructor 傳入 Class 參數, 利用 Class 建立實例
參考 : http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createObjects
Subscribe to:
Posts (Atom)