2016-01-28 56 views
2

我有以下要求。在Java中壓縮和展開對象

假設我有Activity類

class Activity{ 
    String name; 
    String activityId; 
    List<String> activityIds = new ArrayList<>(); 
    // ... 
} 

現在,我的活動(List<Activity>)的列表。有些活動可以 具有相同的名稱,但具有不同的activityIds。 在這種情況下,我想要創建一個空的 activityId和一個activityIds列表的相同的Activity對象。

我也想做相反的事。

我寫了代碼。有一個更好的方法嗎 ?

樣品輸入:

Activity a1 = new Activity("ABC","Mark"); 
Activity a2 = new Activity("1","Boucher"); 
Activity a3 = new Activity("2","Portman"); 
Activity a4 = new Activity("3","Mark"); 
Activity a5 = new Activity("4","Caprio"); 
Activity a6 = new Activity("PQR","Portman"); 
List<Activity> activities = Arrays.asList(a1,a2,a3,a4,a5,a6); 

樣本輸出:

[Activity [name=Portman, activityId=null, activityIds=[2, PQR]] 
, Activity [name=Caprio, activityId=null, activityIds=[4]] 
, Activity [name=Mark, activityId=null, activityIds=[ABC, 3]] 
, Activity [name=Boucher, activityId=null, activityIds=[1]] 
] 

我也希望做相反,它將打印原始列表。

我寫了代碼。 Full code is here有沒有更好的方法來做到這一點?

private static List<Activity> squashDTO(List<Activity> dtoList){  
    List<Activity> filteredActivity = new ArrayList<>(); 
    Map<String, List<Activity>> activityMap = dtoList.stream().collect(Collectors.groupingBy(Activity::getName)); 
    activityMap.forEach((key,value) ->{ 
     Activity a = new Activity(value.get(0).getName()); 
     List<String> activityIds = new ArrayList<>(); 
     for(Activity aa : value){   
      activityIds.add(aa.getActivityId()); 
     } 
     a.setActivityIds(activityIds); 
     filteredActivity.add(a);     
    });  
    return filteredActivity; 
} 

而且expandActivity

private static List<Activity> expandDTO(List<Activity> dtoList){ 
    List<Activity> newList = new ArrayList<Activity>(); 
    for(Activity a : dtoList){ 
     for(String activityId : a.getActivityIds()){ 
      Activity n = new Activity(activityId,a.getName()); 
       newList.add(n); 
     } 
    } 
    return newList; 
} 

回答

3

你想要的是組由活動的名稱,並收集他們的ID添加到列表中。

這是通過使用groupingBy(classifier, downstream)收集器完成的。在這種情況下,下游收集器將每個活動映射到它們的id並將它們收集到一個列表中。有了這個,我們獲得了一張我們需要後處理的地圖來獲得想要的活動列表。因此,這被包裹到collectingAndThen收集器中,其將地圖的每個條目映射到具有null id的Activity

(注:以下假定一個構造public Activity(String activityId, String name, List<String> activityIds)和getter每個屬性)

List<Activity> output = 
    activities.stream() 
       .collect(collectingAndThen(
        groupingBy(
        Activity::getName, 
        mapping(Activity::getActivityId, toList()) 
       ), 
        m -> m.entrySet().stream() 
            .map(e -> new Activity(null, e.getKey(), e.getValue())) 
            .collect(toList()) 
      )); 

爲了使反向和重建輸入列表,我們需要通過活動ID來拉平。在下面的列表中,通過將名稱和ID列表存儲在臨時SimpleEntry(僅用作元組)中,最後將所有這些收集回活動列表中。

List<Activity> input = 
    output.stream() 
      .flatMap(a -> a.getActivityIds().stream().map(l -> new AbstractMap.SimpleEntry<>(l, a.getName()))) 
      .map(e -> new Activity(e.getKey(), e.getValue())) 
      .collect(toList()); 

使用靜態導入:

import static java.util.stream.Collectors.collectingAndThen; 
import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.mapping; 
import static java.util.stream.Collectors.toList;