我们经常再开发的过程中遇到一些字符串拼接的情况,我也是。
但是最近我看了项目中的一些旧代码,就感觉很难受,
就像过七夕,女朋友也想收到巧克力鲜花啥的,总不能一句我爱你就完了。
生活需要仪式,代码也需要巧妙优雅。
先说下坏的示例:
String[] strs = {“a”, “b”, “c”};
需要各个元素进行逗号拼接。
暴力破解是怎样的?
String resultStr = "";
for (String str : strs) {
resultStr = resultStr + str + ",";
}
System.out.println(resultStr.substring(0,resultStr.length()-1));
然后IDEA就提示可以使用StringBuilder:
StringBuilder resultStr = new StringBuilder();
for (String str : strs) {
resultStr.append(str).append(",");
}
System.out.println(resultStr.substring(0,resultStr.length()-1));
这里就不说String 和 StringBuilder,StringBuffer的区别了。
能不能有更好的方式?
可以,Java也是提供了很好的工具类来完成这个任务。就是JDK1.8 为 String 新增的 join 方法。
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
public static String join(CharSequence delimiter,
Iterable<? extends CharSequence> elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
根据方法的状态可以理解成两个方法分别可以对多个字符串 和集合进行拼接。
示例:
// String join(CharSequence delimiter, CharSequence... elements)
String[] strs = {"a", "b", "c"};
System.out.println(String.join(",", "a","b","c"));
System.out.println(String.join(",", strs));
String[] strs = {"a", "b", "c"};
// 集合
List<String> strlist = Arrays.asList(strs);
System.out.println(String.join(",", strlist));
// json
JSONObject jsonObject = new JSONObject();
jsonObject.put("a","aValue");
jsonObject.put("b","bValue");
jsonObject.put("c","cValue");
System.out.println(String.join(",", jsonObject.keySet()));
// idea 提示保存,无法允许
// System.out.println(String.join(",", jsonObject.values()));
Map<String,Object> map = new HashMap<>();
map.put("ak","aMapValue");
map.put("bk","bMapValue");
map.put("ck","cMapValue");
System.out.println(String.join(",", map.keySet()));
// System.out.println(String.join(",", map.values())); // idea 提示保存,无法允许
Map<String,String> map2 = new HashMap<>();
map2.put("ak","aMapValue");
map2.put("bk","bMapValue");
map2.put("ck","cMapValue");
System.out.println(String.join(",", map2.keySet()));
System.out.println(String.join(",", map2.values()));
简单总结以上就是可以对字符串进行操作,集合的话也必须泛型使用字符串。map和json其实也是对其中集合的处理,json本质也是对map的实现。(这里使用fastjson)
JDK1.8 还有一个新的语法糖的更新,其中就有数据流的处理。
我们也可以使用stream进行处理:
System.out.println(Arrays.stream(strs).collect(Collectors.joining(",")));
System.out.println(strlist.stream().collect(Collectors.joining(",")));
json 和 map 仍然和上诉类似。但是其实根据idea提示仍然让我们使用String.join 这是因为我们使用流的情况其实增加了内存上的开销,使解决方案更复杂了。
那么我们什么时候需要使用呢?
其实我们需要不仅仅是字符串拼接的情况下使用流更方便,例如:
System.out.println(jsonObject.values().stream().map(String::valueOf).collect(Collectors.joining(",")));
这里 map(String::valueOf) 就实现了Object 转换成String类型的功能。
加以扩展我们还可以对非字符串数组进行处理。
int[] ints = {1,2,3};
System.out.println(Arrays.stream(ints).mapToObj(String::valueOf).collect(Collectors.joining(",")));
这里 mapToObj(String::valueOf) 实现了基本类型 int 到 String的转换。
Map<String, Object> map3 = new HashMap<>();
Map<String, Object> map4 = new HashMap<>();
map4.put("x","x");
map4.put("z","z");
map3.put("y", map4);
System.out.println(map3.values().stream()
.map(o -> ((Map<String, Object>)o).values())
.map(String::valueOf)
.collect(Collectors.joining(",")));
结果: [x, z]
这里第一个map(o -> ((Map
最后进行拼接,一句完成复杂逻辑。
// lombok
@Data
@AllArgsConstructor
private static class User{
private int id;
private String name;
}
测试:
// POJO对象
User user1 = new User(1, "zhangsan");
User user2 = new User(2, "lisi");
List<User> users = Arrays.asList(user1, user2);
System.out.println(users.stream().map(User::getName).collect(Collectors.joining(",")));
结果: zhangsan,lisi
拼接的时候也不总是逗号,也可以是其他的内容,例如另外的字符,字符串等。
以上就差不多是日常coding时遇到的拼接了,应该可以解决所有的情况。