Java 8 流 - 合并共享相同名称且彼此关注的对象集合

T. *_*hdi 2 java collections java-8 java-stream

假设一个 Person 类:

public class Person {
    private String name;
    private int amount;
}
Run Code Online (Sandbox Code Playgroud)

并假设一个 Person 集合:

persons = [{"Joe", 5}, {"Joe", 8}, {"Joe", 10}, {"Jack", 3}, {"Jack",6}, {"Joe" 4}, 
           {"Joe", 7}, {"Jack", 12}, {"Jack", 15}, {"Luke", 10}, {"Luke", 12}]
Run Code Online (Sandbox Code Playgroud)

我想要的是获取具有相同名称且相互跟随的合并元素的人员列表并求和(使用java 8 Stream);像这样的列表:

Perons = [{"Joe", 23}, {"Jack", 9}, {"Joe", 11}, {"Jack", 27}, {"Luke", 22}]
Run Code Online (Sandbox Code Playgroud)

AJN*_*eld 5

您应该Collector为此创建自己的自定义。

class AdjacentNames {

    List<Person> result = new ArrayList<>();
    Person last = null;

    void accumulate(Person person) {
        if (last != null && last.getName().equals(person.getName())) {
            last.setAmount(last.getAmount() + person.getAmount())
        } else {
            last = new Person(person.getName(), person.getAmount());  // Clone
            result.add(last);
        }
    }

    AdjacentNames merge(AdjacentNames other) {
        List<Person> other_list = other.finisher();

        if (other_list.size() > 0) {
            accumulate(other_list.remove(0));
            result.addAll(other_list);
            last = result.get(result.size()-1);
        }

        return this;
    }

    List<Person> finisher() {
        return result;
    }

    public static Collector<Person, AdjacentNames, List<Person>> collector() {
        return Collector.of(AdjacentNames::new,
                            AdjacentNames::accumulate,
                            AdjacentNames::merge,
                            AdjacentNames::finisher);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用如下:

List<Person> result = persons.stream().collect(AdjacentNames.collector());
Run Code Online (Sandbox Code Playgroud)