【问题标题】:Remove sublists from list while iterating迭代时从列表中删除子列表
【发布时间】:2018-09-26 02:55:59
【问题描述】:

我想计算元素的数量并在它们符合标准时删除一些。使用 collect 和 removeAll 删除不起作用,因为它删除了所有相等的元素,我想删除一个范围而不是全部。 我尝试使用 sublist.clear() 但我得到 ConcurrentModificationException 即使我正在使用 it.remove()。

public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
    int writelndex = 0, count=1;
    List<List<Integer>> toRemove = new ArrayList<>();

    for (int i = 1; i < sortedArr.size(); ++i) {

        if (sortedArr.get(i-1).equals(sortedArr.get(i))) {
            count++;
        } else {
            if(count == m) {
                int nCopies = Math.min(2,m);
                List<Integer> c = sortedArr.subList(writelndex + nCopies, i);
                toRemove.add(c);
            }
            count = 1;
            writelndex = i;
        }
    }

    Iterator<List<Integer>> iterator = toRemove.iterator();
    while (iterator.hasNext()) {
        List<Integer> integers = iterator.next();
        iterator.remove();
        integers.clear();
    }
    return sortedArr;
}

编辑:添加示例:
假设我们有以下列表: (1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5) 和 m = 3。这意味着所有出现 m 次的数字应该发生 2 次 (Math.min(2,3))。所以预期的结果是 (1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5)。

编辑 2:@ShubhenduPramanik 非常优雅地解决了这个任务。 但是,我仍然不清楚为什么会抛出 ConcurrentModificationException,即使我正在使用 iterator.remove() 以及如何在迭代列表时从列表中删除子列表。

【问题讨论】:

  • 您使用的是哪个 Java 版本?
  • @Mansuro 1.8。我也很高兴听到新版本中的解决方案。
  • @Mooshstv 您的问题不清楚。请给出示例输入和预期输出。
  • @ShubhenduPramanik 我添加了一个例子,希望现在更清楚了。

标签: java collections iterator


【解决方案1】:

要获得最优化的解决方案,您应该:
1. 构建要删除的值的索引列表(或集合)
2. 将原始列表中的值移至新列表中,但列出的索引中的值除外。
3. 返回新列表。

这样,您的算法复杂度为 O(2n),比之前的两个答案都更优化。另外,您保持给定列表不变(可以根据您的执行上下文推荐)。最后一个优点是,副本受到青睐,因为列表上的每个删除调用都可能很重(删除索引后的内部对象向左移动:部分隐藏浏览 -_- )

我不会直接给你一个工作代码,让你练习;)。

注意:你的用例对它来说太复杂了,但你应该看看数组列表 API 的 List.removeIf() 代码,它确实优化得很好。这是一篇谈论它的文章:advantages of removeIf method

【讨论】:

    【解决方案2】:

    希望这会有所帮助:

        static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
                //make the count of each element
                Map<Integer, Long> result = sortedArr.stream()
                        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    
    
                for (Map.Entry<Integer, Long> entry : result.entrySet()) {
                    if (entry.getValue() == m) {
                        // Here 2 is hard coded. You can make a variable and pass it to the method with a parameter
                        for (int i = 0; i < m - 2; i++) 
                        {
                            sortedArr.remove(entry.getKey());
                        }
                    }
                }
    
                return sortedArr;
            }
    

    注意:这段代码并不完美,因为我认为m&gt;=2

    【讨论】:

    • 非常感谢。我仍然不明白为什么在我的解决方案中出现异常,你能澄清一下吗?
    【解决方案3】:

    如果我正确理解了任务,那么算法

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Test {
    
        public static void main(String[] args) throws IOException {
    
            int m = 3;
    
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(System.in));
    
            int numbers;
    
            List<Integer> sortedList = new ArrayList<>();
    
            // Fill in the list with values
            for (int i = 0; i < 13; i++) {
                numbers = Integer.parseInt(reader.readLine());
                sortedList.add(numbers);
            }
    
            System.out.println(controlOccurrences(sortedList, m));
    
        }
    
        public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
    
            int count= 1;
    
    
            for (int i = 0; i < sortedArr.size(); i++) {
    
                for (int j = 0; j < sortedArr.size(); j++) {
    
                    if (sortedArr.get(i).equals(sortedArr.get(j)) && i != j) {
    
                      count += 1;
    
                    }
    
                }
    
                if (count == m) {
                    sortedArr.remove(i);
                    count = 1;
                } else {
                    count = 1;
                }
    
            }
    
            return sortedArr;
        }
    
    }
    

    【讨论】:

    • @Mooshstv 总是乐于提供帮助
    猜你喜欢
    • 2011-09-23
    • 2011-03-18
    • 2020-05-27
    • 2021-03-04
    • 2014-10-26
    • 1970-01-01
    • 2011-04-02
    相关资源
    最近更新 更多