在一个列表中找到匹配项并将其删除

时间:2018-12-03 15:57:42

标签: java

我有一个列表,我需要在其中循环浏览并找到匹配项,以便将它们组合在一起并将它们添加到另一个列表中。问题是我在多次迭代某些元素或跳过某些元素方面一直遇到问题。

列表中的对象每个都有两个int值。如果第一个int值是两个元素之间的匹配,则我需要合并两个对象的第二个int值,然后将该对象添加到另一个列表中

如果我有一个列表((12,10), (13,10), (12,5), (14,5), (14,10), (10,20)) 我想将12和14合并为一个新列表 ((12,15), (14,15))和我的原始列表将剩下((13,10), (10,20))

我尝试过使用带有和不带有迭代器的for循环,但是没有运气。

List<Record> finalList = new ArrayList<Record>();

for (int i = 0; i < tempAggregateList.size(); i++){
            Record record = tempAggregateList.get(i);
            for (int j = i+1; j < tempAggregateList.size(); j++){
                Record nextRecord = tempAggregateList.get(j);
                if (record.getFirstValue() == nextRecord.getFirstValue()){
                    record.setSecondValue(record.getSecondValue() + nextRecord.getSecondValue());
                    //then remove nextRecord from tempAggregateList
                }
            }
            finalList.add(record);
        }

以现在的方式,我的第一个for循环将遍历我已经合并并添加到finalList的元素。仅仅删除我添加到finalList的元素是最容易的,但是我还没有找到一种方法。

4 个答案:

答案 0 :(得分:3)

您应该能够使用流:

// group by first value
Map<Integer, Record> newList = list.stream().collect(Collectors.groupingBy(Record::getFirstValue,
       // for each record list for the same first value, add the second one          
       Collectors.collectingAndThen(
            // add first and second value for each pair
            Collectors.reducing((r1, r2) -> new Record(r1.getFirstValue(), r1.getSecondValue() + r2.getSecondValue())),
            // there will be no empty list, so all optionals will be present
            Optional::get));

现在您有了一个Map<Integer, Record>,键是第一个值,键是组合的Record

编辑:我意识到,这样做可以更容易

BinaryOperator<Record> addRecords = (r1, r2) -> new Record(r1.getFirstValue(), r1.getSecondValue() + r2.getSecondValue());

Map<Integer, Record> map = list.stream().collect(
    toMap(Record::getFirstValue, r -> r, addRecords));

,如果您需要列表并在一行中完成

List<Record> result = list.stream().collect(
    collectingAndThen(
        toMap(Record::getFirstValue, r -> r, addRecords),
        m -> new ArrayList<>(m.values())));

暗含从Collectors的静态导入。

答案 1 :(得分:1)

在finalList.add(record)之后,简单地添加tempAggregateList.remove(i);

答案 2 :(得分:0)

这使用groupingBy获得List中的List。如果List的长度大于1,则将其添加到最终列表中。如果List的长度等于1,则将其保留在原始List中。

List<Record> originalList = new ArrayList();
originalList.add(new Record(12, 10));
originalList.add(new Record(13, 10));
originalList.add(new Record(12, 5));
originalList.add(new Record(14, 5));
originalList.add(new Record(14, 10));
originalList.add(new Record(10, 20));

List<Record> finalList = originalList.stream().collect(groupingBy(Record::getFirstValue)).values().stream().filter((t) -> {
    return t.size() > 1; 
}).flatMap(x -> x.stream()).collect(Collectors.toList()).stream().collect(groupingBy(Record::getFirstValue, Collectors.summingInt(Record::getSecondValue))).entrySet().stream().map(t -> new Record(t.getKey(), t.getValue())).collect(Collectors.toList());
finalList.forEach((t) -> {
    System.out.println("(" + t.getFirstValue() + ", " + t.getSecondValue() + ")");
});

originalList = originalList.stream().collect(groupingBy(Record::getFirstValue)).values().stream().filter((t) -> {
    return t.size() == 1;
}).flatMap(x -> x.stream()).collect(Collectors.toList()).stream().collect(groupingBy(Record::getFirstValue, Collectors.summingInt(Record::getSecondValue))).entrySet().stream().map(t -> new Record(t.getKey(), t.getValue())).collect(Collectors.toList());

originalList.forEach((t) -> {
    System.out.println("(" + t.getFirstValue() + ", " + t.getSecondValue() + ")");
});
  

输出

(12, 15)
(14, 15)
(10, 20)
(13, 10)

答案 3 :(得分:0)

仅出于乐趣,迭代,一个Set存储要删除的索引,以及反向迭代以从初始列表中删除项目:

public static void main(String[] args) {
    List<Record> tempAggregateList = new ArrayList<Record>();
    tempAggregateList.add(new Record(12, 10));
    tempAggregateList.add(new Record(13, 10));
    tempAggregateList.add(new Record(12, 5));
    tempAggregateList.add(new Record(14, 5));
    tempAggregateList.add(new Record(14, 10));
    tempAggregateList.add(new Record(10, 20));

    List<Record> finalList = new ArrayList<>();
    Set<Integer> set = new HashSet<>();

    for (int i = 0; i < tempAggregateList.size(); i++) {
        if (!set.contains(i)) {
            Record record = tempAggregateList.get(i);
            int baseValue = record.getFirstValue();
            int sum = record.getSecondValue();
            boolean found = false;

            for (int j = i + 1; j < tempAggregateList.size(); j++) {
                Record nextRecord = tempAggregateList.get(j);
                if (nextRecord.getFirstValue() == baseValue) {
                    found = true;
                    set.add(i);
                    set.add(j);
                    sum += nextRecord.getSecondValue();
                }
            }
            if (found)
                finalList.add(new Record(baseValue, sum));
        }
    }

    for (int i = tempAggregateList.size() - 1; i >= 0; i--) {
        if (set.contains(i))
            tempAggregateList.remove(i);
    }

    for (Record r : tempAggregateList) {
        System.out.print("(" + r.getFirstValue() + ", " + r.getSecondValue() + ") ");
    }

    System.out.println();

    for (Record r : finalList) {
        System.out.print("(" + r.getFirstValue() + ", " + r.getSecondValue() + ") ");
    }
}

将打印:

(13, 10) (10, 20) 
(12, 15) (14, 15)