2016-07-19 103 views
0

我正在尋找一種方法來按字母順序連接字段名稱的對象值。按字母順序連接字段名稱的對象值

例子:

public Class Request { 
    private String number; 
    private String amount; 
    private String currency; 
} 

Request request = new Request(); 
request.setNumber("tata"); 
request.setCurrency("toto"); 

有了這個,我的方法應該返回tototata

方法必須是通用的:

public static String concatenate(Object object) { ...} 

null值不能連接起來。

我已經檢出Apache Commons BeanUtils和Java 8流,但沒有發現任何好處。

+0

你到目前爲止嘗試過什麼? –

+0

爲什麼它會返回「tototata」而不是「tatatoto」,因爲'o'在'a'之後? –

+0

@nickzoum它是基於字段名稱。 –

回答

1

您可以通過迭代給定對象中的所有聲明字段來編寫此代碼。

public static String concatenate(Object object) { 
    return Arrays.stream(object.getClass().getDeclaredFields()) 
       .filter(f -> f.getType() == String.class) 
       .sorted(Comparator.comparing(Field::getName)) 
       .map(f -> { 
         try { return (String)f.get(object); } 
         catch (IllegalAccessException e) { return null; } 
        }) 
       .filter(Objects::nonNull) 
       .collect(Collectors.joining()); 
} 
+1

爲什麼這麼複雜?當你想做類型比較時,爲什麼不進行類型比較,即'.filter(f - > f.getType()== String.class)'?你可以使用'.sorted(Comparator.comparing(Field :: getName))''。而不是手動創建'StringBuilder'並使用臭名昭着的'forEach',只需使用'.collect(Collectors.joining())'就可以達到這個目的... – Holger

+0

順便說一句,這個方法不需要聲明'拋出IllegalAccessException ... ... – Holger

+0

謝謝,這是一個好點 – Andrew

2

感謝您安德魯Tobilko,我這樣做(工作)

public static String concatenateAlphabetically(Object object) { 
     Map<String, String> map = null; 
     try { 
      map = BeanUtils.describe(object); 
     } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
     // remove class attribute generating from BeanUtils.describe 
     map.remove("class"); 
     map.values().removeAll(Collections.singleton(null)); 
     Map<String, String> treeMap = new TreeMap<String, String>(map); 
     return treeMap.values().stream().collect(Collectors.joining()); 
    } 

但我不喜歡用的BeanUtils這個樣子,我喜歡你的方法。

我只是加了f.setAccessible(true);訪問私人領域