我遇到了一个常见的情况,我有一个对象列表,需要生成一个带有单个属性的逗号分隔字符串,然后每个属性都用单引号括起来。
2个例子
public String partIDsToString(List<Part> parts){
StringBuilder sb = new StringBuilder();
for(Part part : parts)
sb.append("'"+part.getPartNumber() + "',");
return sb.substring(0,sb.length()-1);
}
public String companyIDsToString(List<Company> parts){
StringBuilder sb = new StringBuilder();
for(Company c : parts)
sb.append("'"+c.getId() + "',");
return sb.substring(0,sb.length()-1);
}
我将来需要创建更多这样的方法,并且想知道是否有一种方法可以概括这个功能,我正在寻找类似的东西。
public String objectPropertyToString(List<Object> list, Method getProperty){
StringBuilder sb = new StringBuilder();
for(Object obj: list)
sb.append("'"+obj.getProperty() + "',");
return sb.substring(0,sb.length()-1);
}
List<Company> companies = getCompaniesList();//not important
String result = objectPropertyToString(companies , Company::getId);
List<Part> parts= getPartsList();//not important
String result = objectPropertyToString(parts, Part::getPartNumber);
可以使用方法引用/ lambdas或其他任何方式完成吗?
答案 0 :(得分:4)
Stream.map()
和Collectors.joining()
是您的朋友。
companies.stream()
.map(Company::getId)
.map(s -> "'" + s + "'")
.collect(joining(","));
你可以创建一个辅助方法,但根据我的判断,上面的内容非常简洁,不值得:
static <T> String mapAndJoin(Collection<T> c, Function<T,String> f){
return c.stream()
.map(f)
.map(s -> "'" + s + "'")
.collect(joining(","));
}
mapAndJoin(companies, Company::getId);
答案 1 :(得分:2)
如this answer所示,Collectors.joining
可用于生成逗号分隔符列表。但是您也可以使用它将元素一次性用单引号括起来,这比在连接它们之前在每个元素的单独String操作中更有效。
基本思路如下:
public static <T> String objectPropertyToString(
Collection<? extends T> list, Function<T,String> f) {
return list.stream().map(f).collect(Collectors.joining("', '", "'", "'"));
}
我们不是仅用逗号分隔元素,而是使用结束单引号,后跟逗号和开头单引号。此外,我们在第一个元素之前使用开头单引号作为启动器,在最后一个元素之后使用结束单引号。
这很顺利,只有一个例外:如果列表为空,我们得到唯一的''
因为始终生成初始开头报价和尾随结束报价。要解决这个问题,我们必须回顾内部Collectors.joining
的内容,以便了解用于该过程的StringJoiner
,因此我们可以采用内置收集器不提供的方式对其进行配置: / p>
public static <T> String objectPropertyToString(
Collection<? extends T> list, Function<T,? extends CharSequence> f) {
return list.stream().map(f).collect(
()->new StringJoiner("', '", "'", "'").setEmptyValue(""),
StringJoiner::add, StringJoiner::merge).toString();
}
这基本上与之前的尝试相同,但有一个值得注意的例外,即我们现在可以使用setEmptyValue
来指定没有元素的情况下的不同结果。作为奖励,我们现在可以放宽通用类型签名,允许连接任意CharSequence
个实例,而不仅仅是String
s。
用法与以前一样:
List<Company> companies = getCompaniesList();//not important
String result = objectPropertyToString(companies , Company::getId);
List<Part> parts= getPartsList();//not important
String result = objectPropertyToString(parts, Part::getPartNumber);