压平Java对象

时间:2017-06-28 13:04:39

标签: java

我有一个虚拟对象,我需要在Java中展平。 示例

public class DummyObject {
     private String name;

     private List<String> phoneNumbers;

     private List<AddressObject> address;
}

public class AddressObject {
    private List<String> freeTexts; // some random things here.. 

    private String houseNumber;

    private String pinCode;

    private List<FamilyMember> familyMembers;  
}

public class FamilyMember {

    private String memberName;

    private String memberConnection;

    private String memberPhoneNumber;
}

现在我想要展开这个对象并创建一个包含这三个对象的所有条目的新对象列表。所以新的Object(比如说它的FinalObject)将拥有所有这8个条目。

finalObject列表应包含所有唯一条目。

一种方法是运行4个循环。每个列表的每个循环。这将非常混乱。是否有任何优雅的方法来展平DummyObject对象?

我不确定我们是否可以使用java stream或lambda函数来完成它。

public class FinalObject {
     private String name;
     private String phoneNumbers;
     private String freeTexts; // some random things here.. 
     private String houseNumber;
     private String pinCode; 
     private String memberName;
     private String memberConnection;
     private String memberPhoneNumber;
} 

我想到的Sudo代码是

for(phoneNumber : dummyObject.phoneNumbers) {
  for(addr : DummyObject.address) {
     for(freetext : addr.freeTexts) {
        for(familyMember : addr.familyMembers) {
              new FinalObject();
              // fill all fields of FinalObject
        }
     }
  }
}

3 个答案:

答案 0 :(得分:2)

这非常难看,但当你需要展平你的物体时,它看起来像这样:

List<FinalObject> finalObjects = new ArrayList<>();
for(String phoneNumber : dummyObject.getPhoneNumbers()) {
  for(AddressObject addressObject : dummyObject.getAddress()) {
    for (String freeText : addressObject.getFreeTexts()) {
      for (FamilyMember familyMember : addressObject.getFamilyMembers()) {
        finalObjects.add(new FinalObject(dummyObject.getName(), phoneNumber, 
          freeText, addressObject.getHouseNumber(), addressObject.getPinCode(), 
          familyMember.getMemberName(), familyMember.getMemberConnection(), 
          familyMember.getMemberPhoneNumber()));
      }
    }
  }
}

也可以使用Stream

List<FinalObject> finalObjects = Stream.of(dummyObject).flatMap(dummyObj -> dummyObj.getPhoneNumbers().stream()
  .flatMap(phoneNumber -> dummyObj.getAddress().stream()
    .flatMap(addressObject -> addressObject.getFreeTexts().stream()
      .flatMap(freeText -> addressObject.getFamilyMembers().stream()
        .map(familyMember -> new FinalObject(dummyObject.getName(), phoneNumber, freeText,
          addressObject.getHouseNumber(), addressObject.getPinCode(), familyMember.getMemberName(),
          familyMember.getMemberConnection(), familyMember.getMemberPhoneNumber()))
      )
    )
  )).collect(Collectors.toList());

答案 1 :(得分:1)

jan.vogt与flatMap走在正确的轨道上。这是一个示例,需要两个List<String>并在String[]中吐出每个可能的对:

List<String> one = Arrays.asList("1","2","3");
List<String> two = Arrays.asList("4","5","6");

    List<String[]> = one.stream()
        .flatMap((s) -> two.stream().map((t) -> new String[]{s,t}))
        .collect(Collectors.toList());

你们总是会变得更糟糕,因为你必须更多地使用flatMaps,但它在概念上是相同的。真正的诀窍是,来自String的每个one实际上都映射到Streamtwo。然后,s仍然可以将Stream的{​​{1}}的每个元素映射到twoString[]。这会为每对产生一个九项列表。

我写得很快,并没有测试它,但你的应该看起来像这样(注意我忽略了这个例子中字段的私有访问):

address.stream()
.flatMap((Address addressObject) -> phoneNumbers.stream()
         .flatMap((String phoneNumber) -> address.familyMembers.stream()
                  .flatMap((FamilyMember member) -> freeTexts.stream()
                           .map((String text) -> new FinalObject(/* addressObject, phoneNumber, familyMember, and text are all in scope here */)))))
.collect(Collectors.toSet())

此外,要实现此目的,您需要在FinalObject上使用有意义的.equals.hashCode。然后Collectors.toSet()负责使一切都变得独特。我还考虑在您的其他课程中添加.equals.hashCode,并使用Set代替List,以便从一开始就保持独特性。

答案 2 :(得分:0)

我不是Java专家,但我认为您正在寻找某种function replaceStr(string, ...placeholders) { while (placeholders.length > 0) { string = string.replace('%s', placeholders.shift()); } return string; } 操作。也许Java 8已经拥有它,或者你自己定义它是值得的。