Java 按元素将列表拆分为块

Java 按元素将列表拆分为块,java,collections,split,java-8,java-stream,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, typ

我有一组使用此模型的对象(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=.)
]
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);
}
我想按beforeChangement或afterChangement==“”字段拆分此对象列表,以获得此格式(列表列表列表)
List

类似于执行一个反向平面映射,在按字符串“对象”字段进行拆分后,生成一个数组或列表(块)列表

你知道如何使用Streams吗


谢谢大家

假设列表中的对象名为
SOP
对象名为
listSOP
。然后

List<SOP> listSOP = new ArrayList<>();
.... populate your list. 
Map<String,List<SOP>> map = listSOP.stream().collect(Collectors.groupingBy(SOP::getBeforeChangement)
List listSOP=new ArrayList();
.... 填充您的列表。
Map Map=listSOP.stream().collect(收集器.groupingBy(SOP::getBeforeChangement)
这将返回类型为
映射


这里的
getBeforeChangement
SOP
类中的getter方法,它应该返回变量
beforeChangement
的值,这可能会对您有所帮助。

好吧,我在这里会保守一些,我不会使用
s(尽管这是可能的)

以下代码段满足您的需要:

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);
    }
}

注:英语中没有“changement”这样的词。动词“change”中的名词也是“。

嗯,我想用这样一个简单的循环来解决你的问题:

[
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=.)
]
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);
}
List result=new ArrayList();
列表部分=新的ArrayList();
用于(位置:列表位置){
如果(位置getBeforeChangement()等于(“.”)| |位置GetAfterChange()等于(“.”){
result.add(part);//如果条件正确,则将子列表添加到结果列表中
part=new ArrayList();//并重新初始化子列表
}否则{
part.add(pos);//否则只需将pos对象放入子列表
}
}
//如果listPos不以“.”值结尾,则不应转义最后一部分
如果(!part.isEmpty()){
结果.增加(部分);
}

注意,问题还不够清楚,您的对象类名为
SOP
,对象列表是
Pos
哪一个是正确的,在我的回答中,我基于
公共类Pos{..}
而不是
公共类SOP{..}


使用库,您可以使用方法为列表列表拆分列表

例如:

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

这将不起作用:它将把所有的
SOP
s与相同的
beforeChangement
组合在一起,而不是将原始列表划分为有序的子列表。谢谢Tomasz。这个逻辑可以解决我的问题+1@Dr.Mza我更新了代码,所以结果中不包括带句点的元素。谢谢你的回答纠正Pos和SOP是相同的。此解决方案存在一个重大问题,即当
Pos
列表不以
结尾时,您的代码将跳过最后一句话。No@TomaszLinkowski检查问题中的输出,结果中不包括具有
的对象。您还可以与我的回答中提到的问题的输出和演示的输出相比,你是对的,根据问题,包含
的对象应该被跳过(我没有注意到,我的答案也没有)。但我的意思是,如果输入列表没有以“点”结尾-对象,您的代码只是跳过了整个最后一个子列表,而不是包含这样的子列表或抛出错误。请参阅,我从
listPos
中删除了最后一行。请注意
“allez”、“faites”、“vite”、“chers”、“clients”输出中缺少了
。但据我所知,此代码将把点放在单独的列表中,对吗?我们如何排除管道中的“.”而不是与点相关的
映射过滤器(以及额外的收集),我只需使用以下命令:
过滤器(l->!isPeriod(l.get(0)))
where
boolean isPeriod(Pos-Pos){return.“.equals(Pos.beforeChangement)| |”。.equals(Pos.afterChangement);}
@TomaszLinkowski您的示例是,如果第一个元素是“”,则过滤掉整个列表。“-元素现在我更仔细地阅读了代码,我明白句点并没有放在单独的列表中。我感到困惑,因为我认为
groupRuns
中的谓词是
(p1,p2)->!isPeriod(p1)&!isPeriod(p2)
而实际上它是
(p1,p2)->!isPeriod(p2)
。这是一种有点奇怪的情况,因为它意味着句点在列表的开头。但是,你是对的,我的筛选建议不起作用。相反,我会将谓词更改为
(p1,p2)->!isPeriod(p1)
,然后使用
peek
从每个列表中删除最后一个元素(如果它匹配
isPeriod
)。
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());