2014-09-26 59 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(", ", "{", "}")); 
} 
相關問題