循环时删除列表中的元素

时间:2020-06-09 08:03:06

标签: java loops iterator

假设我有一个List<<LogFormat>Log>像这样:

[Log(name = a, accessTime = 5),
Log(name = a, accessTime = 4),
Log(name = a, accessTime = 3),
Log(name = b, accessTime = 10),
Log(name = b, accessTime = 9),
Log(name = c, accessTime = 2),
...]

我想在每个accessTime中保留name的最大值,就像这样:

[Log(name = a, accessTime = 5),
Log(name = b, accessTime = 10),
...]

但是我不知道列表中有多少name个,因此我尝试编写一个循环:

for (LogFormat s : Log) {
  for (LogFormat t : Log) {
    if (s.getName().equals(t.getName())
        && s.getAccessTime() > t.getAccessTime()) {
    Log.remove(t);
    }
  }
}

但是似乎我无法循环使用.remove(),如何解决此问题?

4 个答案:

答案 0 :(得分:0)

您可以使用带有索引的嵌套循环,然后在删除某些内容时从索引中减去:

for (int i = 0; i < s.size() - 1; i++) {
    for (int j = i + 1; j < s.size(); j++) {
        if (...) {
            s.remove(j--)
        }
    }
}

您还需要考虑其他方法(例如,是否需要删除第一个元素)。

但是,我认为最好的解决方案是使用Map,如果适用的话,存储每个日志的最大值。

答案 1 :(得分:0)

尝试一下:

package com.example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    static class Log{
        private int accessTime;
        private String name;

        Log( String name,int accessTime){
            this.accessTime = accessTime;
            this.name = name;
        }
        public int getAccessTime(){
            return this.accessTime;
        }
        public String getName(){
            return this.name;
        }
        @Override
        public String toString(){
            return "{ name = " + name +", accessTime = " + accessTime + "}";
        }
    }   

    public static void main(String[] args) {
        List<Log> l = new ArrayList<>();
        l.add(new Log("a", 5));
        l.add(new Log("a", 4));
        l.add(new Log("a", 3));
        l.add(new Log("b", 10));
        l.add(new Log("b", 9));
        l.add(new Log("c", 2));     

        Map<String, Log> m = new HashMap<>();
        l.stream().forEach( log -> {
            String name = log.getName();
            int accessTime = log.getAccessTime();
            if(m.containsKey(name)){
                if(m.get(name).getAccessTime() < accessTime) {
                    m.put(name, log);
                }
            } else {
                m.put(name, log);
            }
        });
        List<Log> valueList = new ArrayList<>(m.values());

        System.out.println(valueList);
    }
}

输出:

[{name = a,accessTime = 5},{name = b,accessTime = 10},{name = c,accessTime = 2}]

答案 2 :(得分:0)

此带有冒号的 foreach循环是具有“删除”功能的迭代器的语法糖。因此,如果您想以这种方式使用迭代器,则基本上需要访问它:

List<Log> list = new ArrayList<>(Arrays.asList(new Log("a", 1), new Log("b", 5), new Log("a", 4), new Log("b", 2) ));

        for (Iterator<Log> it = list.iterator(); it.hasNext(); ) {
                Log currlog = it.next();
                it.remove();
        }

为了存储具有最大访问时间的日志名称,您可以使用辅助哈希映射并保留每个名称的最大值,并在迭代过程中根据需要对其进行更新

答案 3 :(得分:0)

我会解决这个问题。您的目标是:

我想在每个accessTime中保留name的最大值

Map非常适合这些要求。 name将充当键,而最大的accessTime将是地图的值。

因此,给定类:

class Log {
  String name;
  int accessTime;

  public String getName() {
    return name;
  }

  public int getAccessTime() {
    return accessTime;
  }
}

还有一个Log的列表,称为logs

您只需要将收集器toMap()Math::max用作合并函数:

Map<String, Integer> maxAccessTimeByName = logs.stream()
    .collect(Collectors.toMap(Log::getName, Log::getAccessTime, Math::max));

Math::max确保在发生冲突时选择最大值,即同一键至少出现两次。

现在,您可以按名称访问最长访问时间:

int maxAccessTimeForA = maxAccessTimeByName.get("a");
相关问题