通过元素将列表拆分为多个块

时间:2018-08-09 08:50:10

标签: java collections split java-8 java-stream

我有使用此模型的对象(Pos)集合:

public class Pos {
    private String beforeChangement;
    private String type;
    private String afterChangement;
}

对象列表如下:

[
Pos(beforeChangement=Découvrez, type=VER, afterChangement=découvrir), 
Pos(beforeChangement=un, type=DET, afterChangement=un),
Pos(beforeChangement=large, type=ADJ, afterChangement=large), 
Pos(beforeChangement=., type=SENT, afterChangement=.), 
Pos(beforeChangement=Livraison, type=NOM, afterChangement=livraison), 
Pos(beforeChangement=et, type=KON, afterChangement=et), 
Pos(beforeChangement=retour, type=NOM, afterChangement=retour), 
Pos(beforeChangement=., type=SENT, afterChangement=.), 
Pos(beforeChangement=achetez, type=VER, afterChangement=acheter), 
Pos(beforeChangement=gratuitement, type=ADV, afterChangement=gratuitement), 
Pos(beforeChangement=., type=SENT, afterChangement=.), 
Pos(beforeChangement=allez, type=VER, afterChangement=aller), 
Pos(beforeChangement=faites, type=VER, afterChangement=faire), 
Pos(beforeChangement=vite, type=ADV, afterChangement=vite), 
Pos(beforeChangement=chers, type=ADJ, afterChangement=cher), 
Pos(beforeChangement=clients, type=NOM, afterChangement=client)]
Pos(beforeChangement=., type=SENT, afterChangement=.)
]

我想按beforeChangement或afterChangement ==“”的字段拆分此对象列表。具有这种格式(列表列表)List<List<SOP>>

[

[Pos(beforeChangement=Découvrez, type=VER, afterChangement=découvrir), 
Pos(beforeChangement=un, type=DET, afterChangement=un),
Pos(beforeChangement=large, type=ADJ, afterChangement=large)],

[Pos(beforeChangement=Livraison, type=NOM, afterChangement=livraison), 
Pos(beforeChangement=et, type=KON, afterChangement=et), 
Pos(beforeChangement=retour, type=NOM, afterChangement=retour)],

[Pos(beforeChangement=achetez, type=VER, afterChangement=acheter), 
Pos(beforeChangement=gratuitement, type=ADV, afterChangement=gratuitement)],


[Pos(beforeChangement=allez, type=VER, afterChangement=aller), 
Pos(beforeChangement=faites, type=VER, afterChangement=faire), 
Pos(beforeChangement=vite, type=ADV, afterChangement=vite), 
Pos(beforeChangement=chers, type=ADJ, afterChangement=cher), 
Pos(beforeChangement=clients, type=NOM, afterChangement=client)]

]

就像执行反向flatMap后,将对象的字段拆分为字符串“。”来获得数组列表或列表(块)一样。

您对使用Streams进行操作有任何想法吗?

谢谢你们

5 个答案:

答案 0 :(得分:2)

嗯,我想使用一个简单的循环来解决您的问题:

List<List<Pos>> result = new ArrayList<>();
List<Pos> part = new ArrayList<>();
for(Pos pos : listPos){
    if(pos.getBeforeChangement().equals(".") || pos.getAfterChangement().equals(".")){
        result.add(part);//If the condition is correct then add the sub list to result list
        part = new ArrayList<>();// and reinitialize the sub-list
    } else {
        part.add(pos);// else just put the Pos object to the sub-list
    }
}
//Just in case the listPos not end with "." values then the last part should not be escaped
if(!part.isEmpty()){
    result.add(part);
}

注意,这个问题还不够清楚,您的Object类被命名为SOP,而Object列表是Pos,这是正确的,在我的回答中,我基于public class Pos{..}而不是public class SOP{..}


答案 1 :(得分:2)

通过StreamEx库,您可以使用groupRuns方法将列表拆分为列表列表。

例如:

List<List<Pos>> collect = StreamEx.of(originalList.stream())
            .groupRuns((p1, p2) -> !(".".equals(p2.beforeChangement) || ".".equals(p2.afterChangement)))
            .collect(Collectors.toList());

方法groupRuns返回列表的Stream。在上面的示例中,列出了第一个元素为.的列表。

您可以稍后过滤掉这些元素。例如,使用map方法:

StreamEx.of(originalList.stream())
            .groupRuns((p1, p2) -> !(".".equals(p2.beforeChangement) || ".".equals(p2.afterChangement))) // returns Stream of lists with '.' element
            .map(l -> l.stream()
                        .filter(p -> !(".".equals(p.beforeChangement) || ".".equals(p.afterChangement))) //filter out element with '.'
                        .collect(Collectors.toList()))
            .filter(l -> !l.isEmpty()) // filter out empty lists
            .collect(Collectors.toList());

答案 2 :(得分:1)

好吧,我在这里比较保守,我不会使用Stream(尽管有可能)。

以下代码片段满足您的需求:

List<Pos> posList;
List<List<Pos>> result = new ArrayList<>();
boolean startNewSentence = true;
for (Pos pos : posList) {
    if (startNewSentence) {
        result.add(new ArrayList<>());
    }
    startNewSentence = isPeriod(pos);
    if (!startNewSentence) {
        result.get(result.size() - 1).add(pos);
    }
}

其中:

boolean isPeriod(Pos pos) {
    return ".".equals(pos.beforeChangement()) || ".".equals(pos.afterChangement());
}

PS。请注意,英语中没有“ change”这样的词。动词“ change”中的名词也是“ change”。

答案 3 :(得分:0)

假设您的列表对象名称为SOP,对象名称为listSOP。然后

List<SOP> listSOP = new ArrayList<>();
.... populate your list. 
Map<String,List<SOP>> map = listSOP.stream().collect(Collectors.groupingBy(SOP::getBeforeChangement)

这应该返回类型为Map的{​​{1}}。

<String(BeforeChangement), List<SOP>>是您的getBeforeChangement类中的getter方法,该方法应返回变量SOP的值

答案 4 :(得分:0)

Collectors.groupingBy()可能会对您有所帮助。