我有一个Java类:
class Person {
String firstName;
String lastName;
int income;
public Person(String firstName, String lastName, int income)
{
this.firstName = firstName;
this.lastName = lastName;
this.income = income;
}
我有一个Collection<Person>
,有4个人物对象:
Collection<Person> persons = new ArrayList<>();
persons.add(new Person("John", "Smith", 5));
persons.add(new Person("Mary", "Miller", 2));
persons.add(new Person("John", "Smith", 4));
persons.add(new Person("John", "Wilson", 4));
我想创建一个新的Collection实例,但是来自具有相同&#34; firstName&#34;的元素。和&#34; lastName&#34;,制作1个元素,结果&#34;收入&#34;将是&#34;收入的总和&#34;每个元素。因此,对于这种特殊情况,最终的集合将有3个元素,&#34; John Smith&#34;将有&#34;收入&#34; = 9.
在SQL中,等效查询是:
SELECT FIRSTNAME, LASTNAME, SUM(INCOME) FROM PERSON GROUP BY FIRSTNAME, LASTNAME
我发现只有包含Map作为结果的答案,以及&#34; key&#34;包含用于分组的列。我想从初始(ArrayList<Person>
)直接获得类似的集合,而不是Map,因为如果在我的集合中我有数百万个元素,它将降低代码的性能。我知道如果我在SQL方面工作会更容易,但在这种情况下我必须在Java方面工作。
答案 0 :(得分:2)
我不知道这是否是最美丽的解决方案,但您可以尝试options: () => ({
variables: {
count: 10,
current: 1
},
fetchPolicy: 'network-only',
notifyOnNetworkStatusChange: true
})
groupBy
和firstName
之间的分隔符,让我们来看看说lastName
。在将数据收集到包含.
的{{1}}后,您可以从中创建Map<String, Integer>
的新列表。
firstName.lastName
答案 1 :(得分:1)
我找到了以下答案:
List<Person> collect = persons.stream()
.collect(Collectors.groupingBy(person -> person.getFirstName() + "." + person.getLastName(),
Collectors.summingInt(Person::getIncome)))
.entrySet().stream().map(entry -> new Person(entry.getKey().split(".")[0],
entry.getKey().split(".")[1],
entry.getValue()))
.collect(Collectors.toList());
不要那样做!它使用了很多内存。在您需要分组的字段上使用Wrapper(PersonComparator)。
public class Main {
public static void main(String[] args) {
Collection<Person> persons = new ArrayList<>();
persons.add(new Person("John", "Smith", 5));
persons.add(new Person("Mary", "Miller", 2));
persons.add(new Person("John", "Smith", 4));
persons.add(new Person("John", "Wilson", 4));
Map<Person, Integer> groupedByIncomes = persons.stream()
.collect(
Collectors.groupingBy(
Person::getPersonComparator,
Collectors.summingInt(Person::getIncome)
)
)
.entrySet()
.stream()
.collect(Collectors.toMap(
e -> e.getKey().person,
Map.Entry::getValue
));
System.out.println(groupedByIncomes);
}
static class Person {
String firstName;
String lastName;
int income;
public Person(String firstName, String lastName, int income) {
this.firstName = firstName;
this.lastName = lastName;
this.income = income;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getIncome() {
return income;
}
PersonComparator getPersonComparator() {
return new PersonComparator(this);
}
static class PersonComparator {
Person person;
PersonComparator(Person person) {
this.person = person;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonComparator that = (PersonComparator) o;
if (!person.getFirstName().equals(that.person.getFirstName())) return false;
return person.getLastName().equals(that.person.getLastName());
}
@Override
public int hashCode() {
int result = person.getFirstName().hashCode();
result = 31 * result + person.getLastName().hashCode();
return result;
}
}
}
}
如果你需要框架解决方案f.e.当你需要对你拥有的数据类型(SQL,Mongo或Collections)进行抽象时,我建议你使用QueryDSL:http://www.querydsl.com/
答案 2 :(得分:0)
您可以使用Java 8流'Collector's groupingBy:
Map<String, Integer> sum = items.stream().collect(
Collectors.groupingBy(p -> p.getFirstName()+p.getSecondName(), Collectors.summingInt(Person::getIncome)));
答案 3 :(得分:0)
我认为 JoSQL 是你的方式,它允许你在java对象上运行SQL查询:
JoSQL ( SQL for Java Objects )使开发人员能够将SQL语句应用于Java对象集合。 JoSQL提供了搜索,排序和分组任何Java对象的能力,当你想对Java对象集合执行类似SQL的查询时,应该应用它。
这就是如何在你的情况下使用它:
Query q=new Query();
q.parse("SELECT firstname, lastname, SUM(income) FROM package.Person GROUP BY firstname, lastname");
List<?> results=q.execute(names).getResults();
您也可以按照 JoSQL tutorial 进一步阅读。