java學習-排序及加密簽名時資料排序方式 十大經典排序演算法(動圖演示) Java Comparator字元排序(數字、字母、中文混合排序) 編寫高質量程式碼:改善Java程式的151個建議(第5章:陣列和集合___建議70~74)
排序有兩種
1. 類實現comparable介面呼叫List.sort(null)或Collections.sort(List<T>)方法進行排序
jdk內建的基本型別包裝類等都實現了Comparablel介面,預設是使用自然排序,即升序排序
自定義類實現Comparable介面必須要實現compareTo()方法,自己定義排序方式
2.另一種是List<T>中T類沒有實現comparable介面,又想將物件列表進行排序時,類似於Collections.sort
or Arrays.sort
排序時候使用Comparator介面作為引數進行集合的排序
上面的兩種排序方式底層都是採用歸併排序演算法,是穩定的排序演算法。時間複雜度(nlog2n),空間複雜度(n) 十大經典排序演算法(動圖演示)
使用場景:
1.呼叫別人介面獲取資料時候,需要將引數按照字典排序排序對資料進行簽名,與返回的簽名資料進行對比,驗證資料的完整性。
2.對獲取的資料進行排序後返回給前端,除了使用sql的order asc命令外,也可以使用list.sort方法進行排序後返回給前端(有點傻^^)。
3. 用於複雜的排序場景,比如檔名的排序,廣東-廣州-期末測試1,廣西-桂林-期末測試2,需要我們自己控制排序方法,這時候就需要用到上面兩個排序。
實現Comparable介面的排序
consumInfo.java類
實現comparable介面,使用升序排序
降序就是取反
if (this.price > o.price) {
return -1;
}
if (this.price == o.price) {
return 0;
}
return 1;
public class ConsumInfo implements Comparable<ConsumInfo> {public double price; public String name; public ConsumInfo(double price, String name) { super(); this.price = price; this.name = name; } @Override public int compareTo(ConsumInfo o) { // 首先比較price,如果price相同 if (this.price > o.price) { return 1; } if (this.price == o.price) { return 0; } return -1; } }
來個簡單的測試
ConsumInfo []cc=new ConsumInfo[4]; cc[0] = new ConsumInfo(1.1, "zwh"); cc[1] = new ConsumInfo(2.5, "abc"); cc[2] = new ConsumInfo(0.1, "zwh"); cc[3] = new ConsumInfo(0.1, "cdf"); Arrays.sort(cc); for(ConsumInfo consumInfo:cc) { System.out.println("name:"+consumInfo.name+" price:"+consumInfo.price); }
結果
name:zwh price:0.1
name:cdf price:0.1
name:zwh price:1.1
name:abc price:2.5
如果要先按照price排序,如果price相等,再按name進行升序排序呢
只需要修改conpareTo()方法,在price相等時,在比較name的值
@Override public int compareTo(ConsumInfo o) { // 首先比較price,如果price相同 if (this.price > o.price) { return 1; } if(this.price==o.price) { return this.name.compareTo(o.name); } return -1; }
修改後的輸出結果,
這裡name是String型別,預設是按照字典順序排序,也就是升序排序。
cdf和zwh,,c比z小,所以調換了位置
name:cdf price:0.1 name:zwh price:0.1 name:zwh price:1.1 name:abc price:2.5
使用Comparator介面實現排序
還是使用上面的ConsumInfo.java類
ConsumInfo []cc=new ConsumInfo[4]; cc[0] = new ConsumInfo(1.1, "zwh"); cc[1] = new ConsumInfo(2.5, "abc"); cc[2] = new ConsumInfo(0.1, "zwh"); cc[3] = new ConsumInfo(0.1, "cdf"); Arrays.sort(cc,new Comparator<ConsumInfo>() { @Override public int compare(ConsumInfo o1, ConsumInfo o2) { if(o1.price<o2.price) { return -1; } if(o1.price==o2.price) { return o1.name.compareTo(o2.name); } return 1; } }); for(ConsumInfo consumInfo:cc) { System.out.println("name:"+consumInfo.name+" price:"+consumInfo.price); }
使用了Arrays.sort(T[] a, Comparator<? super T> c)排序方法,會把ConsumInfo所實現的Comparable介面的排序方法替換掉
也就是說只會使用Comparator介面進行排序。
上面的排序是用於List或者陣列或集合的排序,
對於Map,需要對map的key值進行升序排序
使用TreeMap類進行自動排序,預設升序排序。
Map<String, String> para = new TreeMap<String, String>(); para.put("zwh", "123456"); para.put("abc", "123456"); para.put("wuv", "123456"); para.put("cdg", "123456"); for (Map.Entry<String, String> entry : para.entrySet()) { System.out.println("key:" + entry.getKey() + " value:" + entry.getValue()); }
結果
key:abc value:123456
key:cdg value:123456
key:wuv value:123456
key:zwh value:123456
或者我們自己手動對map的key值進行排序 參考:【支付寶,微信支付必備】Java實現url引數按照引數名Unicode碼從小到大排序(字典序)
/** * * 方法用途: 對所有傳入引數按照欄位名的Unicode碼從小到大排序(字典序),並且生成url引數串<br> * 實現步驟: <br> * * @param paraMap 要排序的Map物件 * @param urlEncode 是否需要對value的值進行編碼 * @param keyToLower 是否需要將Key轉換為全小寫 * true:key轉化成小寫,false:不轉化 * @return */ public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) { String buff = ""; Map<String, String> tmpMap = paraMap; try { List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet()); // 對所有傳入引數按照欄位名的 ASCII 碼從小到大排序(字典序) Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() { @Override public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) { return (o1.getKey()).toString().compareTo(o2.getKey()); } }); // 構造URL 鍵值對的格式 StringBuilder buf = new StringBuilder(); for (Map.Entry<String, String> item : infoIds) { if (item.getKey() != null) { String key = item.getKey(); String val = item.getValue(); if (urlEncode) { val = URLEncoder.encode(val, "utf-8"); } if (keyToLower) { buf.append(key.toLowerCase() + "=" + val); } else { buf.append(key + "=" + val); } buf.append("&"); } } buff = buf.toString(); if (buff.isEmpty() == false) { buff = buff.substring(0, buff.length() - 1); } } catch (Exception e) { return null; } return buff; }
參考支付寶的引數排序方法
剔除sign欄位(這個根本不需要剔除,引數中是沒有的),
剔除引數值為空的欄位,這裡做了個簡單的判斷,
對key進行排序,然後用&符號對key=value進行拼接。
Map<String, String> para = new TreeMap<String, String>(); para.put("app_id", "2014072300007148"); para.put("method", "alipay.mobile.public.menu.add"); para.put("charset", ""); para.put("sign_type", ""); para.put("timestamp", "2014-07-24 03:07:50"); para.put("biz_content", ""); para.put("sign_type", "123456"); para.put("version", "1.0"); List<String> keys= new ArrayList<>(para.keySet()); Collections.sort(keys); StringBuffer content=new StringBuffer(); for (int i=0; i<keys.size();i++) { String key = keys.get(i); String value = para.get(key); if(value!=null&&value.length()!=0) { content.append((i==0?"":"&")+key+"="+value); } } System.out.println(content.toString());
結果
app_id=2014072300007148&method=alipay.mobile.public.menu.add&sign_type=123456×tamp=2014-07-24 03:07:50&version=1.0
注意,上面字串的空判斷還少做了一個空白字元的判斷,建議使用下面的值的非空判斷代替
if(value!=null&&value.length()!=0)
public static boolean isBlank(String str) { int strLen; if (str == null || (strLen = str.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if ((Character.isWhitespace(str.charAt(i)) == false)) { return false; } } return true; }
待看:http://www.cnblogs.com/interdrp/p/8970593.html Java Comparator字元排序(數字、字母、中文混合排序)