简体   繁体   中英

Java - map object properties in one list to another list of objects

I have the following two lists which contain objects with the following properties. Data has been included in examples.

List 1 - ShopOwnerMapList

+------------+-------------+
| Owner      | ShopId      |
+------------+-------------+
| Jack       | 67          |
| Sarah      | 69          |
| Sarah      | B7          |
| Tom        | 83          |
| Harry      | 20          |
+------------+-------------+

ShopOwner to ShopIds is a "one to many" relationship. One ShopOwner can have many ids.

List 2 - ShopOwnerList

+------------+------+--------+
| Owner      | Age  | ShopId |
+------------+------+--------+ 
| Jack       | 32   | NULL   | 
| Sarah      | 30   | NULL   |
| Tom        | 45   | NULL   |
| Harry      | 55   | NULL   |
+------------+------+--------+

ShopOwnerList has a property called ShopId which is NULL by default.

How do I now map ShopOwnerMapList to ShopOwnerList using Owner as "key" of sorts? If two instances of Owner exist in ShopOwnerMapList (as with Sarah), then I want the corresponding item in ShopOwnerList to be duplicated. So in effect, after the merge I would end up with:

+------------+------+--------+
| Owner      | Age  | ShopId |
+------------+------+--------+ 
| Jack       | 32   | 67     | 
| Sarah      | 30   | 69     |
| Sarah      | 30   | B7     |
| Tom        | 45   | 83     |
| Harry      | 55   | 20     |
+------------+------+--------+

How can I accomplish this in Java?

I've tried the following but it doesn't extend ShopOwnerList in a case where two instances of Owner exist:

for (int i = 0; i < shopOwnerMapList.size(); i++) {
    for (int j = 0; j < shopOwnerList.size(); j++) {
        ShopOwnerMap shopOwnerMap = shopOwnerMapList.get(i);
        ShopOwner shopOwner = shopOwnerList.get(j);
        if(shopOwnerMap.getOwner().equals(shopOwner.getOwner()) {
            if(shopOwner.getShopId() == null) {
                shopOwner.setShopId(shopOwnerMap.getShopId());            
            }
        }
    }
}

Classes

public class ShopOwnerMap {
   String Owner;
   String ShopId;

   public MyClass() {
   }

   public String getOwner() {
      return this.Owner;
   }

   public void setOwner(String value) {
      this.Owner = value;
   }

   public String getShopId() {
      return this.ShopId;
   }

   public void setShopId(String value) {
      this.ShopId = value;
   }
}

public class ShopOwner { 
   String Owner;     
   String ShopId;    
   Integer Age;     
   String DateOfBirth;

   public ShopOwner() {
   }

   public String getOwner() {
      return this.Owner;
   }

   public void setOwner(String value) {
      this.Owner = value;
   }

   public String getShopId() {
      return this.ShopId;
   }

   public void setShopId(String value) {
      this.ShopId = value;
   }

   public Integer getAge() {
      return this.Age;
   }

   public void setAge(Integer value) {
      this.Age = value;
   }

   public String getDateOfBirth() {
      return this.DateOfBirth;
   }

   public void setDateOfBirth(String value) {
      this.DateOfBirth = value;
   }
}

As I said in the comments, I'd suggest that you rethink your model a bit. First introduce a Shop class:

public class Shop {
    private final String id; // Id of this shop.
    private final ShopOwner owner; // Owner of this shop.
    public Shop(String id, ShopOwner owner) {
        this.id = id;
        this.owner = owner;
    }
    public String getId() { return id; }

    // Overwrite equals and hashcode to allow using Shop as a key in a HashMap (only necessary if you want to enforce uniqueness of a ShopOwner's shops by maintaining a ShopOwner's owned shops using a Map).
    // We simply define equality based on id equality and rely on String.hashCode() (note that this will have to be changed if you want to add additional properties and define equality based on those):
    @Override
    public boolean equals(Object o) {
        return o instanceof Shop && o.toString().equals(this.toString());
    }

    @Override
    public int hashCode() {
        return toString().hashCode();
    }
    @Override
    public String toString() {
        return id;
    }
    // Other properties etc.
}

Change ShopOwner to hold a List of shops that this ShopOwner owns:

public class ShopOwner {
   String owner;
   List<Shop> shops = new ArrayList<>(); // Shops owned by this ShopOwner.
   int age;     
   String dateOfBirth;
   public void addShop(Shop s) {
       // Note that this does NOT guarantee uniqueness of shops if your DB query returns multiple instances of the same shop.
       // If you want this, you could use a Map instead.
       this.shops.add(s);
   }
   // Your other getters etc.
}

As per your comments, you want to retain ShopOwnerMap due to how you interact with your database (I'd personally get rid of this and just instantiate dummy (temporary; with owner field set to null ) Shop s with their respective dummy (read: temporary - later to be replaced by the "real" (already existing) ShopOwner instance found during your matching code) ShopOwner s immediately, but this would require more knowledge of how your code leading up to this problem looks like). What you want to do now is match your List<ShopOwnerMap> with your List<ShopOwner> and add Shop instances to each ShopOwner in the List<ShopOwner> , something like this:

List<ShopOwnerMap> soms = ...; // the list you produced from the DB query.
List<ShopOwner> sos = ...; // your list of ShopOwners, each of which needs to be initialized with the shops they own, i.e. their initial lists of shops are empty.
// Note that the below could be reduced from O(N^2) to O(N) if you manage your ShopOwners using a Map (using an equals+hashCode scheme as suggested for Shop).
for (ShopOwnerMap som : soms) {
    for (ShopOwner so : sos) {
        // We assume that the 'owner' property (perhaps 'name' is more suitable?) is unique among ShopOwners.
        if (som.getOwner().equals(so.getOwner()) {
            // Found the corresponding shop owner; create shop instance and add to list of owned shops.
            so.addShop(new Shop(som.getShopId(), so));
        }
    }
}

Disclaimer: I am tired and kind of rushed this, so it might not be 100% correct, but it should provide you with the general idea. In addition -- as indicated by the comment in parentheses above -- this proposed design is not perfect. That would require more insight into your data model etc.

I'd suggest using guava's Multimap. You can insert multiple values into a single location in the multimap using a key. To implement your solution, you'd essentially need two maps. A Multimap called ShopOwnerMultimap which contains the data in ShopOwnerMapList and also a regular Map called ShopOwnerMap which contains the data in ShopOwnerList. Both maps will use the owner name as the key. When performing your mapping, use the keyset from ShopOwnerMap to grab the values from ShopOwnerMultimap.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM