如何使用方法引用/ java 8来概括实用程序函数

时间:2016-04-15 01:50:07

标签: java java-8

我遇到了一个常见的情况,我有一个对象列表,需要生成一个带有单个属性的逗号分隔字符串,然后每个属性都用单引号括起来。

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或其他任何方式完成吗?

2 个答案:

答案 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);