待整理
編碼習(xí)慣之工具類規(guī)范
Java 編程技巧之?dāng)?shù)據(jù)結(jié)構(gòu)
概述
工具類的選擇順序:
語言自帶(java)>專用工具類(apache=guava)>容器(spring)>組件附帶工具類(dubbo,zk)
字符串操作
List集合轉(zhuǎn)成字符串:1,2,3
List<String> idList = Arrays.asList("1", "2", "3");
//方法一:命令式編程
StringBuilder str = new StringBuilder();
for (int i = 0; i < idList.size(); i++) {
if (i == 0) {
str.append(idList.get(i));
} else {
str.append(idList.get(i)).append(",");
}
}
System.out.println(str.toString());//1,2,3
//方法一:命令式編程
StringBuilder builder = new StringBuilder();
if (!idList.isEmpty()) {
builder.append(idList.get(0));
for (int i = 1, n = idList.size(); i < n; i++) {
builder.append(",").append(idList.get(i));
}
}
System.out.println(builder.toString());//1,2,3
//方法二:java8實(shí)現(xiàn)
String ids = idList.stream().reduce((a, b) -> a + "," + b).orElse("");
System.out.println(ids);//1,2,3
//方法三:StringJoiner實(shí)現(xiàn):函數(shù)式編程
String idsJoining = idList.stream().collect(Collectors.joining(","));
System.out.println(idsJoining);//1,2,3
//方法四:guava實(shí)現(xiàn): 函數(shù)式編程
String idsJoin = Joiner.on(",").skipNulls().join(idList);
System.out.println(idsJoin);//1,2,3
//引申:java8 StringJoiner 其它功能
StringJoiner sj2 = new StringJoiner(":", "[", "]");
idList.stream().forEach(sj2::add);
System.out.println(sj2.toString());//[1:2:3]
java8
數(shù)據(jù)導(dǎo)入
如果需要對excel導(dǎo)入到數(shù)據(jù)庫中近尚,可以先將excel文件轉(zhuǎn)換為csv文件敛惊,再生成插入sql臼勉。
@Test
public void importCsv() throws Exception {
String path = "/Users/zhangshaolin/Documents/data.csv";
Stream<String> lines = Files.lines(Paths.get(path), Charset.defaultCharset());
lines.forEach(line -> {
String[] lineStr = line.split(",");
String id = lineStr[0];
String oldUserId = lineStr[1];
});
}
多線程
List<CompletableFuture<String>> completableFutures =
Lists.newArrayList("1","2","3").stream().map(i -> CompletableFuture.supplyAsync(() ->i ))
.collect(Collectors.toList());
List<String> strings = completableFutures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
List:
public static List<String> dataList = Collections.synchronizedList(new ArrayList<String>());
Map:
public static Map<String,String> dataMap = new ConcurrentHashMap <String,String>();
apache
使用Pair實(shí)現(xiàn)成對結(jié)果的返回
在C/C++語言中虽抄,Pair(對)是將兩個(gè)數(shù)據(jù)類型組成一個(gè)數(shù)據(jù)類型的容器,比如std::pair。
Pair主要有兩種用途:
(1) 把key和value放在一起成對處理昔穴,主要用于Map中返回名值對冬念,比如Map中的Entry類;
(2) 當(dāng)一個(gè)函數(shù)需要返回兩個(gè)結(jié)果時(shí)崇渗,可以使用Pair來避免定義過多的數(shù)據(jù)模型類字逗。
第一種用途比較常見,這里主要說明第二種用途宅广。
在JDK中葫掉,沒有提供原生的Pair數(shù)據(jù)結(jié)構(gòu),也可以使用Map::Entry代替跟狱。
不過俭厚,Apache的commons-lang3包中的Pair類更為好用,函數(shù)使用案例:
//java entry實(shí)現(xiàn)
AbstractMap.SimpleEntry<Boolean, BigDecimal> entry = new AbstractMap.SimpleEntry<>(Boolean.TRUE, BigDecimal.ZERO);
System.out.println(entry.getKey() + ":" + entry.getValue());
//java entry實(shí)現(xiàn):不可變對象
AbstractMap.SimpleImmutableEntry<Boolean, BigDecimal> immutableEntry = new AbstractMap.SimpleImmutableEntry<>(Boolean.TRUE, BigDecimal.ZERO);
System.out.println(immutableEntry.getKey() + ":" + immutableEntry.getValue());
//pair實(shí)現(xiàn)驶臊,同ImmutablePair:不可變對象
Pair pair = Pair.of(Boolean.TRUE, BigDecimal.ZERO);
System.out.println(pair.getLeft() + ":" + pair.getRight());
Pair<Boolean, BigDecimal> immutablePair = ImmutablePair.of(Boolean.TRUE, BigDecimal.ZERO);
System.out.println(immutablePair.getLeft() + ":" + immutablePair.getRight());
//可變pair實(shí)現(xiàn): MutablePair
MutablePair<Boolean, BigDecimal> mutablePair = new MutablePair();
mutablePair.setLeft(Boolean.TRUE);
mutablePair.setRight(BigDecimal.ZERO);
System.out.println(mutablePair.getLeft() + ":" + mutablePair.getRight());
//參數(shù)支撐類
public class Holder<T> {
private volatile T value;
public Holder(T value) {
this.value = value;
}
public static <T> Holder<T> valueOf(T value) {
return new Holder(value);
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
@Test
public void Holder() {
Holder<String> strHolder = Holder.valueOf("AAA");
changeStr(strHolder);
System.out.println(strHolder.getValue());//BBB
Holder<Integer> intHolder = Holder.valueOf(1);
changeInt(intHolder);
System.out.println(intHolder.getValue());//2
}
private void changeStr(Holder<String> a) {
a.setValue("BBB");
}
private void changeInt(Holder<Integer> a) {
a.setValue(2);
}
雙向Map
JDK中的Map要求鍵必須唯一挪挤,而雙向Map(Bidirectory Map)則要求鍵、值都必須唯一关翎,也就是鍵值是一一對應(yīng)的扛门,此類Map的好處就是既可以根據(jù)鍵進(jìn)行操作,也可以反向根據(jù)值進(jìn)行操作纵寝,比如刪除论寨、查詢等,示例代碼如下:
Apache commons項(xiàng)目還有很多非常好用的工具店雅,如DBCP政基、net、Math等闹啦,但是這些包有個(gè)缺點(diǎn)沮明,大部分更新比較緩慢,有些擴(kuò)展類甚至可以說比較陳舊了窍奋,例如Collections中的大部分集合類不支持泛型荐健,這讓一些“泛型控”們很不舒服酱畅,總想自己再封裝一下,提供一些泛型支持江场,這就需要讀者在項(xiàng)目開發(fā)中自行考慮了纺酸。
guava
多值Map
多值Map比較簡單,在JDK中址否,Map中的一個(gè)鍵對應(yīng)一個(gè)值餐蔬,在put一個(gè)鍵值對時(shí),如果鍵重復(fù)了佑附,則會(huì)覆蓋原有的值樊诺,在大多數(shù)情況下這比較符合實(shí)際應(yīng)用,但有的時(shí)候確實(shí)會(huì)存在一個(gè)鍵對應(yīng)多個(gè)值的情況音同,比如我們的通訊錄词爬,一個(gè)人可能會(huì)對應(yīng)兩個(gè)或三個(gè)號碼,此時(shí)使用JDK的Map就有點(diǎn)麻煩了权均。在這種情況下顿膨,使用Guava的Multimap可以很好地解決問題,
代碼如下:
//多值MapMultimap<String,String> phoneBook = ArrayListMultimap.create();
phoneBook.put("張三", "110");
phoneBook.put("張三", "119");System.out.println(phoneBook.get("張三"));
輸出的結(jié)果是一個(gè)包含兩個(gè)元素的Collection叽赊,這是一種很巧妙的處理方式恋沃,可以方便地解決我們開發(fā)中的問題。
Table表
在GIS(Geographic Information System蛇尚,地理信息系統(tǒng))中芽唇,我們經(jīng)常會(huì)把一個(gè)地點(diǎn)標(biāo)注在一個(gè)坐標(biāo)上,比如把上海人民廣場標(biāo)注在北緯31.23取劫、東經(jīng)121.48的位置上,也就是說只要給出了準(zhǔn)確的經(jīng)度和緯度就可以進(jìn)行精確的定位—兩個(gè)鍵決定一個(gè)值研侣,這在Guava中是使用Table來表示的谱邪,示例代碼如下:
Table<Double,Double,String> g = HashBasedTable.create();
//定義人民廣場的經(jīng)緯度坐標(biāo)g.put(31.23, 121.48, "人民廣場");
//輸出坐標(biāo)點(diǎn)的建筑物
g.get(31.23,121.48);
其實(shí)Guava的Table類與我們經(jīng)常接觸的DBRMS表非常類似,可以認(rèn)為它是一個(gè)沒有Schema限定的數(shù)據(jù)表庶诡,
比如:
//Table惦银,完全類似于數(shù)據(jù)庫表
Table<Integer,Integer,String> user = HashBasedTable.create();
//第一行、第一列的值是張三
user.put(1, 1, "張三");
//第一行末誓、第二列的值是李四
user.put(1,2,"李四");
//第一行第一列是誰
user.get(1,1);