2014-09-26 74 views
4
protected static String paramsAsString(Object[] args) { 
    return Arrays.stream(args).map((o) -> o != null && o.getClass().isArray() ? ArrayUtils.toString(o) : o) 
      .collect(Collectors.toList()).toString(); 
} 

单元测试有什么方法可以简化这个流表达式?

public void paramsAsString() throws Exception { 
    String[] strings = {"1" , "2"}; 
    int[] ints = {3,4}; 
    int[] intsEmpty = {3,4}; 
    Object[] args = {"aaa" ,"zzz" , ints , strings, intsEmpty, null}; 
    String paramsAsString = paramsAsString(args); 
    assertEquals("[aaa, zzz, {3,4}, {1,2}, {3,4}, null]", paramsAsString); 
} 

我刚学流API。 我不知道有没有什么方法来简化这个流表达式并删除复杂的if?

+0

我想不出除了将'map'的参数提取到实用程序方法之外,并且使用此方法的句柄代替。 – Marco13 2014-09-26 08:21:01

+2

您是否知道['Arrays.deepToString'](http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#deepToString(java.lang.Object []))?它确实代码是关于你的代码的,它不会在'[]'和'{}'括号之间切换... – Holger 2014-09-26 08:27:53

+0

你可以做的一件事就是替换'.collect(Collectors.toList())。toString() ;'用'.collect(收藏家。加入(“,”,“[”,“]”));'以避免不必要的中间'List'创建。 – Holger 2014-09-26 08:35:15

回答

5

如果你只是参考ArrayUtils::toString,您避免条件:

protected static String paramsAsString(Object[] args) { 
    return Arrays.stream(args) 
       .map(ArrayUtils::toString) 
       .collect(Collectors.toList()).toString(); 
} 

,但你的测试失败beause你:的

[aaa, zzz, {3,4}, {1,2}, {3,4}, {}]

代替

[aaa, zzz, {3,4}, {1,2}, {3,4}, null]

你可以“砍”这与正则表达式:

return Arrays.stream(args) 
       .map(ArrayUtils::toString) 
       .collect(Collectors.toList()) 
       .toString().replaceAll("\\{\\}" , "null"); 
} 

但就个人而言,我会保持条件和拉姆达转换为另一种实用方法:

public class MyArrayUtils { 
    protected static String paramsAsString(Object[] args) { 
     return Arrays.stream(args) 
         .map(MyArrayUtils::objectToString) 
         .collect(Collectors.toList()).toString(); 
    } 

    private static String objectToString(Object object) { 
     return object == null ? null : ArrayUtils.toString(object); 
    } 
} 
4

这我不清楚你所期望的输出是否真的是你想要的,或者它只是你当前代码的一个工件(即结合第三方库方法ArrayUtils.toString(o)的输出与List.toString)。

当您只需使用Arrays.deepToString你已经得到

"[aaa, zzz, [3, 4], [1, 2], [3, 4], null]" 

如果你真的想使用Stream API作为一个练习,或者要加强对格式实际控制,你可以这样来做:

使用java.lang.reflect.Array

public class MyArrayUtil { 
    static String paramsAsString(Object o) { 
     if(o==null) return "null"; 
     if(!o.getClass().isArray()) return o.toString(); 
     return IntStream.range(0, Array.getLength(o)) 
      .mapToObj(i->Array.get(o, i)).map(MyArrayUtil::paramsAsString) 
      .collect(Collectors.joining(", ", "{", "}")); 
    } 
} 

这确实不隐藏任何实用程序方法的用法,但可以自行格式化任何数组。并且它不会创建中间List以使用其toString()方法。相反,它使用适当的Collector,它允许您控制输出。在上面的例子中,我使用{}这样的结果将是:

{aaa, zzz, {3, 4}, {1, 2}, {3, 4}, null} 

如果你想要更高的性能可能会牺牲可读性和使用下面的派生代码:

static String paramsAsString(Object o) { 
    if(o==null) return "null"; 
    if(!o.getClass().isArray()) return o.toString(); 
    Stream<String> stream; 
    if (o instanceof Object[]) { 
     stream=Arrays.stream((Object[]) o).map(MyArrayUtil::paramsAsString); 
    } 
    else if (o instanceof int[]) { 
     stream=Arrays.stream((int[])o).mapToObj(String::valueOf); 
    } 
    else if (o instanceof long[]) { 
     stream=Arrays.stream((long[])o).mapToObj(String::valueOf); 
    } 
    else if (o instanceof double[]) { 
     stream=Arrays.stream((double[])o).mapToObj(String::valueOf); 
    } 
    else stream=IntStream.range(0, Array.getLength(o)) 
     .mapToObj(i->Array.get(o, i)).map(Object::toString); 
    return stream.collect(Collectors.joining(", ", "{", "}")); 
}