Java 如何创建对象列表的摘要?
我认为这是一个非常基本的问题,应该有解决办法,但我没有找到任何办法。我想我需要更多的术语方面的帮助,我应该查阅哪些术语来了解我的问题,但我真的非常感谢任何帮助 无论如何,我想实现以下几点:Java 如何创建对象列表的摘要?,java,list,sorting,arraylist,Java,List,Sorting,Arraylist,我认为这是一个非常基本的问题,应该有解决办法,但我没有找到任何办法。我想我需要更多的术语方面的帮助,我应该查阅哪些术语来了解我的问题,但我真的非常感谢任何帮助 无论如何,我想实现以下几点: plum -> Sum X = 10, Product Y = 25 apple -> Sum X = 6, Product Y = 8 pear -> Sum X = 6, Product Y = 12 peach -> Sum X = 1, Product Y = 2 我有一个物
plum -> Sum X = 10, Product Y = 25
apple -> Sum X = 6, Product Y = 8
pear -> Sum X = 6, Product Y = 12
peach -> Sum X = 1, Product Y = 2
我有一个物品清单。每个对象的形式如下所示:
public class ExampleClass {
private String name;
private Double firstDouble;
private Double secondDouble;
+ constructor and a bunch of methods
}
基本上,我有一个名称变量和一组与ExampleClass的每个实例相关联的数字。name变量不是id,因此列表中可能有几个ExampleClasses具有相同的名称,它们都具有不同的关联数字。我想做的是从这个列表中创建一个“摘要”:
- 筛选出具有相同名称的ExampleClass的每个实例,因此在我的最终对象列表中,没有两个具有相同名称变量的对象
- 我想用同名对象的双变量进行操作
ExampleClass first = new ExampleClass("apple",1,4);
ExampleClass second = new ExampleClass("pear",6,12);
ExampleClass third = new ExampleClass("apple",5,2);
ExampleClass fourth = new ExampleClass("peach",1,2);
ExampleClass fifth = new ExampleClass("plum",10,25);
在本例中,我想从列表中删除第一个或第三个元素,因为它们具有相同的名称,并且我想对数字进行运算,比如将1和5相加,将4和2相乘
提前谢谢你的帮助
编辑:我可以用一堆循环来解决它。然而,我需要我的代码是可读的,并且尽可能地高效。我不是在寻找带有嵌套循环的暴力解决方案,我感兴趣的是是否有一个好的或更好的解决方案。而不是
ExampleClass first = new ExampleClass("apple",1,4);
ExampleClass second = new ExampleClass("pear",6,12);
ExampleClass third = new ExampleClass("apple",5,2);
ExampleClass fourth = new ExampleClass("peach",1,2);
ExampleClass fifth = new ExampleClass("plum",10,25);
使用列表
List<ExampleClass> list = new ArrayList<>(5);
list.add(new ExampleClass("apple",1,4));
...
我想其他的你可以自己做。你应该读一下列表、地图、集合等等
筛选出具有相同名称的ExampleClass的每个实例,因此在我的最终对象列表中,没有两个具有相同名称变量的对象
SortedSet
收集,例如在将项目添加到列表之前,您可以使用任何
集合
继承的集合提供的方法,这样,如果该方法返回true
,您就可以处理重复项。建议您使equals
实现与compariable
实现保持一致。在Java 8中,查找按名称分组的所有X值的总和非常容易:
// Find the sum of X and group by name
Map<String, Integer> sumXByName = Stream.of(first, second, third, fourth, fifth)
.collect(groupingBy(ExampleClass::getName,
Collectors.<ExampleClass>summingInt(e -> e.getX())));
// Print the results
sumXByName.entrySet().stream()
.map(e -> e.getKey() + " -> " + e.getValue())
.forEach(System.out::println);
但是,查找X和Y的乘积需要一个自定义收集器
static class ExampleStatistics implements Consumer<ExampleClass> {
private Integer sum = 0;
private Integer product = null;
@Override
public void accept(ExampleClass value) {
sum += value.getX();
if (product == null) {
product = value.getY();
} else {
product *= value.getY();
}
}
public ExampleStatistics combine(ExampleStatistics other) {
sum += other.sum;
product *= other.product;
return this;
}
public Integer getSum() {
return sum;
}
public Integer getProduct() {
return product;
}
@Override
public String toString() {
return String.format("Sum X = %d, Product Y = %d", sum, product);
}
}
static class ExampleSummarizer
implements Collector<ExampleClass, ExampleStatistics, ExampleStatistics> {
@Override
public Supplier<ExampleStatistics> supplier() {
return ExampleStatistics::new;
}
@Override
public BiConsumer<ExampleStatistics, ExampleClass> accumulator() {
return (r, t) -> r.accept(t);
}
@Override
public BinaryOperator<ExampleStatistics> combiner() {
return (r, t) -> r.combine(t);
}
@Override
public Function<ExampleStatistics, ExampleStatistics> finisher() {
return i -> i; // identity finish
}
@Override
public Set<Collector.Characteristics> characteristics() {
return Stream.of(Characteristics.IDENTITY_FINISH, Characteristics.UNORDERED)
.collect(toSet());
}
};
编辑:为了方便起见,我使用了整数。但是,也有适用于双精度的汇总等价物,例如summingDouble
class ExampleClass {
private final String name;
private final Integer x;
private final Integer y;
public ExampleClass(String name, Integer x, Integer y) {
super();
this.name = name;
this.x = x;
this.y = y;
}
public String getName() {
return name;
}
public Integer getX() {
return x;
}
public Integer getY() {
return y;
}
}
所以你有没有试过自己去解决它?。与其从
ExampleClass
中创建N个对象,不如创建一个数组,循环遍历它,并将每个元素的名称与数组的其余部分进行比较,然后执行所需的操作。@Frakcool我可以使用头优先的方法来解决它,创建一组循环,并在整个过程中进行交互。还有更好的选择吗?谷歌:“java按名称分组元素”->使用一些排序算法(快速排序,…)并按“水果”排序,然后在一个循环中比较相邻元素并执行操作。删除第一个和第三个元素将使用列表完成。删除(0);列表。删除(1)代码>(或list.remove(2);list.remove(0);
,如果您愿意的话)。但我不认为这是问题的关键。一个HashMap
可能会更好。即使是哈希集
。
// Summarize all examples and group by name
Map<String, ExampleStatistics> statsByName = Stream.of(first, second, third, fourth, fifth)
.collect(groupingBy(ExampleClass::getName, new ExampleSummarizer()));
plum -> Sum X = 10, Product Y = 25
apple -> Sum X = 6, Product Y = 8
pear -> Sum X = 6, Product Y = 12
peach -> Sum X = 1, Product Y = 2
class ExampleClass {
private final String name;
private final Integer x;
private final Integer y;
public ExampleClass(String name, Integer x, Integer y) {
super();
this.name = name;
this.x = x;
this.y = y;
}
public String getName() {
return name;
}
public Integer getX() {
return x;
}
public Integer getY() {
return y;
}
}