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

时间:2016-03-20 17:03:11

标签: java list arraylist

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

List<Clause> clauses = new ArrayList<Clause>();

在每个条款中,我想要一个名为forwardClauses

的子句子列表

我希望每个条款在其forwardClauses中添加一个给定的x个子句,这些子句在它过滤掉了作为WeirdClause实例的子句之后。我也不关心WeirdClauses所具有的前瞻性。

所以 NormalClause extends ClauseWeirdClause extends Clause

列表

[
NormalClause(uuid=1), 
NormalClause(uuid=2), 
NormalClause(uuid=3), 
WeirdClause(uuid=4), 
NormalClause(uuid=5)
]
如果x = 2(= 2条款向前),

应该给我第一个

uuid=1
forwardClauses = [NormalClause(uuid=2), NormalClause(uuid=3)]

uuid=2
forwardClauses = [NormalClause(uuid=3), NormalClause(uuid=5)]

uuid=3
forwardClauses = [NormalClause(uuid=5)]

uuid=4
forwardClauses = []

uuid=5
forwardClauses = []

所以这是我提出问题后的第一个实现(没有检查过):

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

编辑:改进版本O(N)基于nukie的回答利用O(1)list.get(i)

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

无论发生什么事情都是O(N ^ 2)并且为下一个元素保留指针的方法将是微不足道的但是在这里它们必须等于forwardClausesNum并且除此之外一些元素不计算所以指针我相信不会工作。

如果我能采取更高效的替代方案,我们将不胜感激。谢谢

2 个答案:

答案 0 :(得分:1)

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

  1. 获取列表的尾部(除第一个之外的所有元素)
  2. 通过使用forwardClausesNum限制尾部来设置第一个元素的forward子句。
  3. 使用尾部递归调用函数。
  4. 如果列表为空,则表示您已完成。
  5. 编辑: 如果您正在使用Java 8,我认为这可能会解决您的问题。但是,它可以更有效地完成,但除非性能是一个非常大的问题,否则这应该足够了。

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

答案 1 :(得分:0)

我想,你可以这样试试:

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

由于您没有为函数设置返回值,因此我将此示例编写为副作用函数。但是当然你可以将结果放在其他一些集合中。