Java 如何从具有特定类约束的列表中获取x个下一项

Java 如何从具有特定类约束的列表中获取x个下一项,java,list,arraylist,Java,List,Arraylist,我有一个不同类型对象的列表,我们称之为子句 List<Clause> clauses = new ArrayList<Clause>(); 如果x=2(=2条向前),第一条应该给我 因此,这是我在提出问题(尚未检查)后的第一个实现: publicstaticvoidsetforward子句(列表子句,int-forwardClausesNum){ for(int i=0;i!(c古怪子句实例)) .collect(Collectors.toList()); RECSET

我有一个不同类型对象的列表,我们称之为子句

List<Clause> clauses = new ArrayList<Clause>();
如果x=2(=2条向前),第一条应该给我

因此,这是我在提出问题(尚未检查)后的第一个实现:

publicstaticvoidsetforward子句(列表子句,int-forwardClausesNum){
for(int i=0;i<子句.size();i++){
子句=子句.get(i);
if(古怪子句实例){
继续;
}
int forwardClausesToGo=forwardClausesNum;
对于(int j=i+1;j0&!(forwardClauseInstanceof WeirdClause)){
条款。添加转发条款(转发条款);
前进的路——;
}
}
}
}
编辑:基于nukie的答案O(1)列表的改进版O(N)。获取(i)

private void lookforward子句(列表0){
子句forward子句=子句.get(i+j);
if(!(forwardClause instanceof WeirdClause)){
条款。添加转发条款(转发条款);
前进的路——;
}
j++;
}
}
}
我想到的是O(N^2),为下一个元素保留指针的方法很简单,但这里它们必须等于forwardClausesNum,而且有些元素不被计算,所以我认为指针不起作用


如果有更好的选择,我将不胜感激:)谢谢

我认为这可能是一个很好的方法:

  • 获取列表的尾部(除第一个元素外的所有元素)
  • 通过使用
    forwardClausesNum
    限制尾部,设置第一个元素的forward子句
  • 用尾部递归调用函数
  • 如果列表为空,则完成
  • 编辑: 如果您使用的是Java8,我认为这可能会解决您的问题。虽然这样做可能效率更高,但除非性能真的是一个大问题,否则这就足够了

    public static void setForwardClauses(List<Clause> clauses, int num) {
        List<Clause> normalClauses = 
               clauses.stream()
                      .filter(c -> !(c instanceof WeirdClause))
                      .collect(Collectors.toList());
    
        recSetForwardClauses(normalClauses);
    }
    
    private static void recSetForwardClauses(List<Clause> clauses, int num) {
        if(clauses.isEmpty()) return;
    
        List<Clause> tail = 
               clauses.stream().skip(1).collect(Collectors.toList());
    
        List<Clause> limited =
               tail.stream().limit(num).collect(Collectors.toList());      
    
        clauses.get(0).setForwardClauses(limited);
    
        recSetForwardClauses(tail);
    }
    
    publicstaticvoidsetforward子句(列表子句,int-num){
    列表子句=
    子句.stream()
    .过滤器(c->!(c古怪子句实例))
    .collect(Collectors.toList());
    RECSETFORWARD条款(普通条款);
    }
    私有静态void RecSetForwardClaires(列表子句,int num){
    if(子句.isEmpty())返回;
    列表尾=
    子句.stream().skip(1).collect(collector.toList());
    名单有限公司=
    tail.stream().limit(num.collect(Collectors.toList());
    条款。get(0)。SetForward条款(有限);
    RECSETFORWARD条款(尾部);
    }
    
    我想,您可以这样尝试:

    public static void setForwardClauses(List<Clause> clauses, int forwardClausesNum) {
       int counter=0;
       Clause current = clauses.get(counter);
       //skip leading WeirdClauses
       do {
         counter++;         
       } while (current instanceOf WeirdClause);
    
       if (current instanceOf WeirdClause)
         return;
       int group = 0;
       for (counter = counter + 1; counter < clauses.size();counter++){
         if (clauses.get(counter) instanceOf WeirdClause)
           continue;
         if (group == forwardClausesNum) {
           current = clauses.get(current);
           group = 0;
         } else {
           current.forwardClauses.add(clauses.get(counter));
           group++;
         }
       }
    }
    
    publicstaticvoidsetforward子句(列表子句,int-forwardClausesNum){
    int计数器=0;
    当前子句=子句.get(计数器);
    //跳过前导奇怪子句
    做{
    计数器++;
    }while(weird子句的当前实例);
    if(WeirdClause的当前实例)
    返回;
    int组=0;
    for(计数器=计数器+1;计数器<子句.size();计数器++){
    if(子句.get(counter)instanceOf weird子句)
    继续;
    如果(组==forwardClausesNum){
    当前=子句。获取(当前);
    组=0;
    }否则{
    current.forward子句.add(子句.get(计数器));
    组++;
    }
    }
    }
    

    因为您没有将返回值放入函数,所以我编写了这个示例作为副作用函数。当然,你也可以把结果放在其他的收藏中。

    我没有要求特定的代码——如果需要的话,我可能会得到一笔赏金。但是想到的一切都是O(N^2)复杂的。我曾想过使用指针来跟踪下一个元素,这很简单,但forwardNum是动态的,一些元素必须被过滤掉。我将发送我所拥有的内容soon@marstran我发送了我所做的-它没有被检查是的,当然,将
    WeirdClause
    s添加到转发子句时,将其删除。另外,当第一个元素是
    WeirdClause
    时,请跳过设置forwardClauses。谢谢!这是一种使用递归的有趣方法——这种方法的空间和时间复杂度是多少?它在任何方面都比迭代方法好吗?如果我没有弄错的话,这种方法在时间和空间复杂性上都是O(n)。您可以使用
    列表
    上的
    子列表
    -方法,以便在获取尾部和限制尾部时不必迭代元素。但是,请注意,此方法会在原始列表上创建一个视图。这意味着,如果您更改原始列表,则所有子列表也将更改。您可能还希望在调用该方法之前过滤掉所有
    WeirdClause
    s,因此您不必一直“重新过滤”列表。不过,我仍然需要初始列表中的WeirdClause:)谢谢!当它发现古怪的子句时,它不会停止计数(count++)吗?我只想跳过它们。这似乎有O(N)的时间复杂度,这将是理想的。请检查我的代码以了解预期的行为。是的,此实现将跳过古怪的子句。continue语句只将循环路由到下一个迭代,而不执行循环块中的提醒代码。我认为我们的解决方案基本相同。哦,是的,列表。get(I)应该是O(1),因为这是一个arraylisthmm。。。。事实上,跳过最初的奇怪条款没有多大意义)我认为这是我思维流动的结果)
    public static void setForwardClauses(List<Clause> clauses, int forwardClausesNum) {
        for (int i = 0; i< clauses.size(); i++){
            Clause clause = clauses.get(i);
            if(clause instanceof WeirdClause){
                continue;
            }
            int forwardClausesToGo = forwardClausesNum;
            for(int j = i+1; j < clauses.size(); j++){
                Clause forwardClause = clauses.get(j);  
                if(forwardClausesToGo > 0 && !(forwardClause instanceof WeirdClause)){
                    clause.addForwardClause(forwardClause);
                    forwardClausesToGo--;
                }
            }
        }
    }
    
        private void lookForwardClauses(List<Clause clauses, int forwardClausesNum) {
            for (int i = 0; i< clauses.size(); i++){
                Clause clause = clauses.get(i);
                if(clause instanceof InnerText){
                    continue;
                }
                int forwardClausesToGo = forwardClausesNum;
                int j = 1;
                while(i+j < clauses.size() && forwardClausesToGo > 0) {
                    Clause forwardClause = clauses.get(i+j);
                    if(!(forwardClause instanceof WeirdClause)){
                        clause.addForwardClause(forwardClause);
                        forwardClausesToGo--;
                    }
                    j++;
                }
            }
        }
    
    public static void setForwardClauses(List<Clause> clauses, int num) {
        List<Clause> normalClauses = 
               clauses.stream()
                      .filter(c -> !(c instanceof WeirdClause))
                      .collect(Collectors.toList());
    
        recSetForwardClauses(normalClauses);
    }
    
    private static void recSetForwardClauses(List<Clause> clauses, int num) {
        if(clauses.isEmpty()) return;
    
        List<Clause> tail = 
               clauses.stream().skip(1).collect(Collectors.toList());
    
        List<Clause> limited =
               tail.stream().limit(num).collect(Collectors.toList());      
    
        clauses.get(0).setForwardClauses(limited);
    
        recSetForwardClauses(tail);
    }
    
    public static void setForwardClauses(List<Clause> clauses, int forwardClausesNum) {
       int counter=0;
       Clause current = clauses.get(counter);
       //skip leading WeirdClauses
       do {
         counter++;         
       } while (current instanceOf WeirdClause);
    
       if (current instanceOf WeirdClause)
         return;
       int group = 0;
       for (counter = counter + 1; counter < clauses.size();counter++){
         if (clauses.get(counter) instanceOf WeirdClause)
           continue;
         if (group == forwardClausesNum) {
           current = clauses.get(current);
           group = 0;
         } else {
           current.forwardClauses.add(clauses.get(counter));
           group++;
         }
       }
    }