基于两个属性的对象折叠阵列列表生成唯一的集合



我有一个重新组织一组数据的特定问题。目前,我的数据保存在以下类的阵列列表中:

class MyRecord {
    private String location;
    private ArrayList<EmployeeCategory> employeeCategory;}
class EmployeeCategory {
    private String category;
    private String employee;
}

例如 ArrayList<MyRecord> myRecordList;

我看起来像以下数据(我以Jsonike结构进行了显示(:

{location: "Houston", {category: "purchasing", employee: "John"}},
{location: "Houston", {category: "sales", employee: "John"}},
{location: "Houston", {category: "purchasing", employee: "Hank"}},
{location: "Houston", {category: "field operations", employee: "Hank"}},
{location: "Houston", {category: "sales", employee: "Jane"}},
{location: "Houston", {category: "purchasing", employee: "Jane"}},
{location: "Houston", {category: "human resources", employee: "Jane"}},
{location: "Dallas", {category: "purchasing", employee: "Matt"}},
{location: "Dallas", {category: "field operations", employee: "Matt"}},
{location: "Dallas", {category: "human resources", employee: "Todd"}},
{location: "Dallas", {category: "field operations", employee: "Todd"}},
{location: "Dallas", {category: "sales", employee: "Todd"}},
{location: "Dallas", {category: "purchasing", employee: "June"}},
{location: "Dallas", {category: "human resources", employee: "June"}}

我想简化该数据,然后将其重组为以下类的数组列表:

class MyCollapsedRecord {
    private String location;
    private String name;
    private ArrayList<String> employee;
}

以使数据处于以下形式:

{location:"Houston", category:"purchasing", employee:["John", "Hank", "Jane"]},
{location:"Houston", category:"sales", employee:["John", "Jane"]},
{location:"Houston", category:"field operations", employee:["Hank"]},
{location:"Houston", category:"human resources", employee:["Jane"]},
{location:"Dallas", category:"purchasing", employee:["Matt", "June"]},
{location:"Dallas", category:"field operations", employee:["Matt", "Todd"]},
{location:"Dallas", category:"human resources", employee:["Todd", "June"]},
{location:"Dallas", category:"sales", employee:["Todd"]}

我认为最好的策略将涉及基于位置和类别对生成独特的记录。我尝试在覆盖等值和hashvalue方法的同时使用linkedhashset,但我相信我的数据结构对于这种应用程序来说太复杂了。我想我可能需要采用更手动的方法来嵌套以进行循环,例如这种算法,但是我无法将头缠绕以将其修改为更复杂的情况。

这是我到目前为止重组的尝试:

ArrayList<MyRecord> myRecordArrayList = new ArrayList<>();
//Load data to myRecordArrayList
ArrayList<CollapsedRecord> myCollapsedArrayList = new ArrayList<>();
for (int i = 0; i < myRecordArrayList.size(); i++) {
    boolean isDistinctLocation = false;
    for (int j=0; j < i; j++) {
        if (myRecordArrayList.get(i).getLocation().equals(myRecordArrayList.get(j).getLocation())) {
            isDistinctLocation = true;
            for (int m = 0; m < myRecordArrayList.get(i).getEmployeeCategory().size(); m++) {
                boolean isDistinctCategory = false;
                for (int n = 0; n < m; n++) {
                    if (myRecordArrayList.get(i).getEmployeeCategory().get(m).getCategory().equals(myRecordArrayList.get(i).getEmployeeCategory().get(n).getCategory())) {
                        isDistinctCategory = true;
                        CollapsedRecord tempCollapsedRecord = new CollapsedRecord();
                        tempCollapsedRecord.setLocation(myRecordArrayList.get(i).getLocation());                            tempCollapsedRecord.setCategory(myRecordArrayList.get(i).getEmployeeCategory().get(m).getCategory());    
                    }
                }
            }    
            break;
        }
    }
    if (!isDistinctLocation) {
        System.out.println(myRecordArrayList.get(i).getLocation());
    }    
}

如何完成?

您的代码不基于您认为正确的策略:

  • 定义一个由位置和类别组成的键,定义hashcode和equals;
  • 使用该键存储与该键关联的所有员工。

只是这样做,这将更简单:

public final class Key {
    private final String location;
    private final String category;
    // TODO constructor, getters, equals and hashCode
}

现在只使用一张地图:

Map<Key, List<String>> employeesByKey = new HashMap<>();
for (MyRecord record : myRecordList) {
    for (EmployeeCategory ec : record.getEmployeeCategories()) {
        Key key = new Key(record.getLocation(), ec.getCategory());
        employeesByKey.computeIfAbsent(key, k -> new ArrayList<String>()).add(ec.getEmployee());
    }
}
List<MyCollapsedRecord> result = 
    employeesByKey.stream()
                  .map(entry -> new MyCollapsedRecord(entry.getKey().getLocation(), entry.getKey().getCategory(), entry.getValue()));
                  .collect(Collectors.toList());

最新更新