Java 从大量集合中遍历和分组相似对象的有效方法

Java 从大量集合中遍历和分组相似对象的有效方法,java,data-structures,java-8,grouping,Java,Data Structures,Java 8,Grouping,我目前正在致力于一个实现,基本上涉及到处理对象的arraylist,比如1000,在它们的属性中找到共性并对它们进行分组 比如说 ArrayList itemList<CustomJaxbObj> = {Obj1,obj2,....objn} //n can reach to 1000 arraylistitemlist={Obj1,obj2,….objn}//n可以达到1000 对象属性-注册年份、位置、金额 分组标准-对于具有相同注册年份和位置的对象…添加金额 如果有10个对

我目前正在致力于一个实现,基本上涉及到处理对象的arraylist,比如1000,在它们的属性中找到共性并对它们进行分组

比如说

ArrayList itemList<CustomJaxbObj> = {Obj1,obj2,....objn} //n can reach to 1000
arraylistitemlist={Obj1,obj2,….objn}//n可以达到1000
对象属性-注册年份、位置、金额

分组标准-对于具有相同注册年份和位置的对象…添加金额

如果有10个对象,其中8个对象具有相同的loc和注册年份,则添加所有8个对象以及注册年份和loc匹配的其他2个对象的金额。因此,在操作结束时,我只剩下两个对象。1是8个匹配对象的总和,1是2个匹配对象标准的总和

目前我使用的是双重传统循环。高级循环更好,但它们不能对索引提供太多控制,我需要对索引进行分组。它允许我跟踪哪些单独的条目组合在一起形成一个分组条目的新条目

for (i = 0; i < objlist.size(); i++) {
  for(j = i+1; j< objList.size();j++){
    //PErform the check with if/else condition and traverse the whole list
   }
}
(i=0;i{ 对于(j=i+1;j 虽然这样做的工作,看起来非常低效和过程繁重。有没有更好的办法。我看到了其他要求我使用Java8流的答案,但是操作很复杂,因此需要进行分组。我举了一个例子,当有一场比赛时,我会做一些事情,但不仅仅是添加

有没有更好的方法?是否有更好的数据结构来保存此类数据,从而使搜索和分组更容易

添加更多视角,为之前未提供此信息表示歉意

arraylist是来自传入负载xml的jaxb对象的集合

XML继承权

    <Item>
<Item1>
    <Item-Loc/>
    <ItemID>
    <Item-YearofReg/>
    <Item-Details>
        <ItemID/>
        <Item-RefurbishMentDate>
        <ItemRefurbLoc/>
    </Item-Details>
</Item1>
<Item2></Item2>
<Item3></Item3>
....
</Item>

....
因此Item的Jaxb对象有一个900-1000项的列表。每个项目可能都有一个子部分ItemDetails,它有一个翻新日期。我面临的问题是,当没有项目细节部分时,双循环工作正常,并且每个项目都可以遍历和检查。要求说,如果项目已翻新,然后我们忽略了它的一年的Reg,而不是考虑翻新,以符合标准。 另一点是,项目详细信息不必属于该部分中的同一项目,也就是说,项目1的项目详细信息可以出现在项目2的项目详细信息部分中,项目id是用于将正确项目映射到其项目详细信息的字段

这意味着除非我已经阅读了完整的列表,否则我无法开始进行更改。正常的for循环可以做到这一点,但它会增加圈复杂度,因为双循环已经增加了圈复杂度

因此,在执行分组之前,首先需要一个数据结构来存储和分析对象列表


抱歉之前没有提到这一点。我在stackoverflow中的第一个问题就是缺乏经验。

您可以使用散列来添加具有相同注册年份和位置的元素数量

不100%确定您的最终目标是什么,但这里有一些东西可以让您开始。要按这两个属性分组,可以执行以下操作:

Map<String, Map<Integer, List<MyObjectType>>> map = itemList.stream()
                .collect(Collectors.groupingBy(MyObjectType::getLoc,
                         Collectors.groupingBy(MyObjectType::getYear)));
Map Map=itemList.stream()
.collect(收集器).groupingBy(MyObject类型::getLoc,
Collectors.groupingBy(MyObjectType::getYear));

上面的解决方案假设
getLoc
是一个类型
String
getYear
是一个类型
Integer
,然后您可以执行进一步的流操作以获得所需的总和。

您可以使用
收集器。groupingBy(分类器,下游)
采集器。将其汇总为下游采集器。您没有发布对象的类,所以我请假定义了自己的类。但想法是相似的。我还使用了
AbstractMap.SimpleEntry
作为最终映射的键

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class GroupByYearAndLoc {
    static class Node {
        private Integer year;
        private String loc;
        private int value;

        Node(final Integer year, final String loc, final int value) {
            this.year = year;
            this.loc = loc;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        List<Node> nodes = new ArrayList<>();
        nodes.add(new Node(2017, "A", 10));
        nodes.add(new Node(2017, "A", 12));
        nodes.add(new Node(2017, "B", 13));
        nodes.add(new Node(2016, "A", 10));

        Map<AbstractMap.SimpleEntry<Integer, String>, Integer> sums = nodes.stream()
                // group by year and location, then sum the value.
                .collect(Collectors.groupingBy(n-> new AbstractMap.SimpleEntry<>(n.year, n.loc), Collectors.summingInt(x->x.value)));
        sums.forEach((k, v)->{
            System.out.printf("(%d, %s) = %d\n", k.getKey(), k.getValue(), v);
        });
    }
}

我会将“Year+Location”连接为hashmap中的键,然后让该映射保存与每个唯一键相关联的任何内容。然后您就可以有一个“for循环”(不是嵌套循环)。这是最简单的方法。

你能举一个你目前用来存储对象的累加器的例子吗?。在这个问题上增加了一些见解,希望能有所帮助。目前,我将所有内容存储在ArrayList中,并在条件匹配时执行操作。这将创建一个映射图,可能OP正在查找一个按分组的键。这可能会有所帮助,但我必须满足一个新的要求,我最近了解到了这一点,并对问题进行了一些更新。道歉。这确实有助于使用JAVA8传送带方法提高效率。@KarthikRK别误会我的意思,但是你的编辑应该会带来一些澄清,但这只会让问题变得更糟。我已经读了三遍了,还是不知道你的意思是什么problem@KarthikRK今天晚些时候休息一下,我会看看你的编辑。现在,我已经推出了一个带有双循环的构建,因为我已经等了很长时间才完成。将在下一版本中重做java类。我可能会尝试晓峰.李给出的方法,修改后的AominèStreams方法看起来是我应该走的路。你的回答确实有助于思考过程。我仍然需要考虑满足我最近增加的新要求。不过谢谢你!
(2017, A) = 22
(2016, A) = 10
(2017, B) = 13