Reputation: 13206
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;
}
}
Upvotes: 1
Views: 2248
Reputation: 2336
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.
Upvotes: 1
Reputation: 11
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.
Upvotes: 0