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:

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;
        }
    }