I have three HashMap of this generic type HashMap<String,Server> but I want to combine the data of all the HashMap based on my unique key. But only Server pojo has different data.
So first hashmap has some servers information like ip_address and server name therefore I have both values in map and ip_address as key. Then I have some other hardware spec stored in other map and ip_address as key and so same in third map.
Therefore, combining all POJO based on key I will get complete server information with corresponding ip_address.
I don't know how to do it without doing nested operation
Here is a way to do this. I have shown the example code using only two Map collections, and, the third can be applied in similar way.
I am using Map's computeIfPresent method to "merge" the values of the two maps. The BiFunction (the argument for the computeIfPresent) need to take care of the "merging" aspect - any validations, etc., presently not known (to me). Also, see the note below on computeIfPresent.
Example code:
import java.util.*;
import java.util.function.*;
public class CombiningMaps {
private static Map<String, ServerInfo> map1 = new HashMap<>();
private static Map<String, ServerInfo> map2 = new HashMap<>();
private static BiFunction<String, ServerInfo, ServerInfo> combineWithMap2 =
(k, v) -> {
if (map2.get(k) != null) {
ServerInfo v2 = map2.get(k);
// combine values of map1 and map2
v.setHw2(v2.getHw2());
}
return v;
};
public static void main(String [] args) {
// Add some test data to map 1
map1.put("serv1", new ServerInfo("0A", "a1", "",""));
map1.put("serv2", new ServerInfo("0B", "b1", "",""));
map1.put("serv3", new ServerInfo("0C", "c1", "",""));
System.out.println(map1);
// Add some data to map 2
map2.put("serv1", new ServerInfo("0A", "", "a2",""));
map2.put("serv2", new ServerInfo("0B", "", "b2",""));
map2.put("serv3", new ServerInfo("0C", "", "c2",""));
System.out.println(map2);
// Update map1 with map 2's info
map1.forEach((k,v) -> map1.computeIfPresent(k, combineWithMap2));
System.out.println(map1);
}
}
class ServerInfo {
private String ipAddr;
private String hw1; // hw stands for hardware related info
private String hw2;
private String hw3;
public ServerInfo(String ipAddr, String hw1, String hw2, String hw3) {
this.ipAddr = ipAddr;
this.hw1 = hw1;
this.hw2 = hw2;
this.hw3 = hw3;
}
public String getIpAddr() {
return ipAddr;
}
public String getHw1() {
return hw1;
}
public void setHw1(String s) {
hw1 = s;
}
public String getHw2() {
return hw2;
}
public void setHw2(String s) {
hw2 = s;
}
public String getHw3() {
return hw3;
}
public void setHw3(String s) {
hw3 = s;
}
public String toString() {
return ipAddr + ":" + hw1 + "-" + hw2 + "-" + hw3;
}
}
The output:
{serv2=0B:b1--, serv3=0C:c1--, serv1=0A:a1--}
{serv2=0B:-b2-, serv3=0C:-c2-, serv1=0A:-a2-}
{serv2=0B:b1-b2-, serv3=0C:c1-c2-, serv1=0A:a1-a2-}
How the computeIfPresent behaves (some scenarios):
Consider a Map<String, Integer> map with keys and values: {four=4, one=1, ten=10, two=2, three=3, five=5, eleven=11, twelve=null}
(1) updates the mapping with new value (note the lambda is a BiFunction returning a newly computed value):
map.computeIfPresent("ten", (k, v) -> new Integer(100));
(2) the function returns a null, the existing mapping is removed:
map.computeIfPresent("eleven", (k, v) -> null);
(3) the mapping is not added, as there is no existing mapping:
map.computeIfPresent("twenty", (k, v) -> new Integer(20));
(4) the existing value is null, so there is no change:
map.computeIfPresent("twelve", (k, v) -> new Integer(12));
After getting all values in three maps I used finalMap to combine values. Here is the working for it since the key is same in all map therefore getting key of map using key of
map1 was a good idea.
Set<Map.Entry<String, Server>> set1 = map.entrySet();
for (Map.Entry<String, Server> me : set1) {
Server server=new Server();
server.setIp_Address(me.getKey());
server.setServerName(me.getValue().getServerName());
server.setOsName(map1.get(me.getKey()).getOsName());
server.setOsVersion(map1.get(me.getKey()).getOsVersion());
server.setOsArchitecture(map1.get(me.getKey()).getOsArchitecture());
server.setHardDiskCapacity(map1.get(me.getKey()).getHardDiskCapacity());
server.setRamCapacity(map1.get(me.getKey()).getRamCapacity());
server.setAvgNetWorkUtilizationSent(map2.get(me.getKey()).getAvgNetWorkUtilizationSent());
server.setAvgNetworkUtilizationReceived(map2.get(me.getKey()).getAvgNetworkUtilizationReceived());
server.setAvgCPUtilization(map2.get(me.getKey()).getAvgCPUtilization());
server.setAvgRamUtilization(map2.get(me.getKey()).getAvgRamUtilization());
finalMap.put(me.getKey(), server);
}
Set<Map.Entry<String, Server>> set2 = finalMap.entrySet();
for (Map.Entry<String, Server> me : set2) {
System.out.println(" ServerIP : "+ me.getValue().getIp_Address()+"\t"+" Server Name :"+me.getValue().getServerName()+"\t \t"+" Hardware Capacity :"+me.getValue().getHardDiskCapacity()+"\t"+" Average CPU Utlization: "+me.getValue().getAvgCPUtilization());
}
Use putAll():
Map<String, Server> all = new HashMap<>();
all.putAll(map1);
all.putAll(map2);
all.putAll(map3);
If you want a one-liner:
Map<String, Server> all = Stream.of(map1, map2, map3)
.reduce(new HashMap<>(), (a, b) -> {a.putAll(b); return a;});
Collisions result in replacement.
Your problem it to merge two POJO classes.
For example
class Server {
private String ipAddr;
private String hw1;
private String hw2;
private String hw3;
//Getter and Setters
}
Server s1 = new Server("0A", "a1", null, null);
Server s2 = new Server("0A", null, "b2", null);
So the merged pojo should be like this.
Server merged = merge(s1, s2);// Server{ipAddr=0A, hw1=a1, hw2=b2, hw3=null}
The merge function looks like this...
public static Server merge(Server s1, Server s2) throws Exception {
Server merged = new Server();
for (Field field : Server.class.getDeclaredFields()) {
field.setAccessible(true);
Object getS1 = field.get(s1);
Object getS2 = field.get(s2);
if(getS1 == null && getS2 != null) {
field.set(merged, getS2);
} else if (getS1 != null && getS2 == null) {
field.set(merged, getS1);
} else { //equal values
field.set(merged, getS1);
}
}
return merged;
}
Here is the example code to merge three maps, Its kinda quick and dirty but works well.
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
class MergeMaps {
public static void main(String[] args) throws Exception {
Map<String, Server> map1 = new HashMap<>();
Map<String, Server> map2 = new HashMap<>();
Map<String, Server> map3 = new HashMap<>();
// Add some test data to map 1
map1.put("serv1", new Server("0A", "a1", null, null));
map1.put("serv2", new Server("0B", "b1", null, null));
System.out.println(map1);
// Add some data to map 2
map2.put("serv1", new Server("0A", null, "a2", null));
map2.put("serv2", new Server("0B", null, "b2", null));
map2.put("serv3", new Server("0C", null, "c2", null));
System.out.println(map2);
// Add some data to map 3
map3.put("serv1", new Server("0A", null, null, "a3"));
map3.put("serv2", new Server("0B", null, null, "b3"));
map3.put("serv3", new Server("0C", null, null, "c3"));
map3.put("serv4", new Server("0D", null, null, "d4"));
System.out.println(map3);
Map<String, Server> resultingMap = new HashMap<>();
resultingMap.putAll(map1);
for (Map.Entry<String, Server> entry : map2.entrySet()) {
if (resultingMap.containsKey(entry.getKey())) {
Server s = resultingMap.get(entry.getKey());
Server t = entry.getValue();
Server merged = merge(s, t);
resultingMap.put(entry.getKey(), merged);
} else {
resultingMap.put(entry.getKey(), entry.getValue());
}
}
for (Map.Entry<String, Server> entry : map3.entrySet()) {
if (resultingMap.containsKey(entry.getKey())) {
Server server1 = resultingMap.get(entry.getKey());
Server server2 = entry.getValue();
Server merged = merge(server1, server2);
resultingMap.put(entry.getKey(), merged);
} else {
resultingMap.put(entry.getKey(), entry.getValue());
}
}
System.out.println(resultingMap);
}
public static Server merge(Server s1, Server s2) throws Exception {
Server merged = new Server();
for (Field field : Server.class.getDeclaredFields()) {
field.setAccessible(true);
Object getS1 = field.get(s1);
Object getS2 = field.get(s2);
if (getS1 == null && getS2 != null) {
field.set(merged, getS2);
} else if (getS1 != null && getS2 == null) {
field.set(merged, getS1);
} else {
field.set(merged, getS1);
}
}
return merged;
}
}
class Server {
private String ipAddr;
private String hw1;
private String hw2;
private String hw3;
public Server() {
}
public Server(String ipAddr, String hw1, String hw2, String hw3) {
this.ipAddr = ipAddr;
this.hw1 = hw1;
this.hw2 = hw2;
this.hw3 = hw3;
}
//Getter and setters
#Override
public String toString() {
return "Server{" + "ipAddr=" + ipAddr + ", hw1=" + hw1 + ", hw2=" + hw2 + ", hw3=" + hw3 + '}';
}
}
The output looks like this..
{serv2=Server{ipAddr=0B, hw1=b1, hw2=null, hw3=null}, serv1=Server{ipAddr=0A, hw1=a1, hw2=null, hw3=null}}
{serv2=Server{ipAddr=0B, hw1=null, hw2=b2, hw3=null}, serv3=Server{ipAddr=0C, hw1=null, hw2=c2, hw3=null}, serv1=Server{ipAddr=0A, hw1=null, hw2=a2, hw3=null}}
{serv2=Server{ipAddr=0B, hw1=null, hw2=null, hw3=b3}, serv3=Server{ipAddr=0C, hw1=null, hw2=null, hw3=c3}, serv4=Server{ipAddr=0D, hw1=null, hw2=null, hw3=d4}, serv1=Server{ipAddr=0A, hw1=null, hw2=null, hw3=a3}}
{serv2=Server{ipAddr=0B, hw1=b1, hw2=b2, hw3=b3}, serv3=Server{ipAddr=0C, hw1=null, hw2=c2, hw3=c3}, serv4=Server{ipAddr=0D, hw1=null, hw2=null, hw3=d4}, serv1=Server{ipAddr=0A, hw1=a1, hw2=a2, hw3=a3}}
Related
I have a nested list of maps as below
Example List of Maps:
[{owner=trader1, ord_id=[ord1, ord2], watchlist=trader1_WL}, {owner=trader2, ord_id=[ord3, ord4], watchlist=trader2_WL}]
I need to convert it into a map of ord_id:owner
Output Required:
{ord1:trader1, ord2:trader1, ord3:trader2, ord4.trader2}
Sample Code:[Doesn't work as ord_id has list of items]
import java.util.*;
import java.util.stream.Collectors;
public class Main
{
public static void main (String[]args)
{
Map < String, Object > order1 = new HashMap <> ();
order1.put ("ord_id", Arrays.asList ("ord1", "ord2"));
order1.put ("owner", "trader1");
order1.put ("watchlist", "trader1_WL");
Map < String, Object > order2 = new HashMap <> ();
order2.put ("ord_id", Arrays.asList ("ord3", "ord4"));
order2.put ("owner", "trader2");
order2.put ("watchlist", "trader2_WL");
List < Map < String, Object >> open_order_list = new ArrayList <> ();
open_order_list.add (order1);
open_order_list.add (order2);
System.out.println (open_order_list);
Map < String, String > result =
open_order_list.stream ().collect (Collectors.
toMap (s->(String) s.get ("ord_id"),
s->(String) s.get ("owner")));
System.out.println (result);
}
}
It's ugly, but you can do it like this:
Map<String, String> result = open_order_list.stream()
.flatMap(obj -> {
String owner = (String) obj.get("owner");
#SuppressWarnings("unchecked")
List<String> ord_id = (List<String>) obj.get("ord_id");
return ord_id.stream().map(id -> new String[] { owner, id });
})
.collect(Collectors.toMap(a -> a[1], a -> a[0]));
The code would be a lot better if you parsed the JSON text into POJOs, instead of generic collection objects.
List<Order> open_order_list = Arrays.asList(
new Order("trader1", "trader1_WL", "ord1","ord2"),
new Order("trader2", "trader2_WL", "ord3","ord4") );
System.out.println(open_order_list);
Map<String, String> result = open_order_list.stream()
.flatMap(ord -> ord.getOrd_id().stream().map(id -> new String[] { ord.getOwner(), id }))
.collect(Collectors.toMap(a -> a[1], a -> a[0]));
System.out.println (result);
class Order {
private final String owner;
private final String watchlist;
private final List<String> ord_id;
public Order(String owner, String watchlist, String... ord_id) {
this.owner = owner;
this.watchlist = watchlist;
this.ord_id = Arrays.asList(ord_id);
}
public String getOwner() {
return this.owner;
}
public String getWatchlist() {
return this.watchlist;
}
public List<String> getOrd_id() {
return this.ord_id;
}
#Override
public String toString() {
return "Order[owner=" + this.owner + ", watchlist=" + this.watchlist + ", ord_id=" + this.ord_id + "]";
}
}
I have a Hashmap map<String, List<Student>>.
Student {
String name;
List<Date> absentDates;
}
Key Values pairs as follows:
["Class1",<Student1 absentDates = [02/11/2010, 02/09/2010]><Student2 absentDates = [02/10/2010]>]
["Class2",<Student3 absentDates = [02/12/2010]>]
["Class3",<Student4 absentDates = null>]
How can I sort this map using java 8 steams as follows, based on map value ie, List.get(0).getAbsentDates().get(0) ie, a nullable absentDates of first Student object in each list
Expected output is
["Class2",<Student3 absentDates = [02/12/2010]>]
["Class1",<Student1 absentDates = [02/11/2010, 02/09/2010]><Student2 absentDates = [02/10/2010]>]
["Class3",<Student4 absentDates = null>]
Steps I followed.
Map<String, List> Stream through the entrySet
convert to class MapValues{Key,List}. MapValue is the Custom wrapper class created to hold key and value
Implement Comaparator for MapValues based on stundents.get(0).getAbsentDates().get(0) and also handle null in comaprator
Collect using Collectors.toMap to preserve the order use LinkedHashMap
In Short the
Map<String, List<Student>> newmap = map.entrySet()
.stream()
.map(e -> new MapValues(e.getKey(), e.getValue()))
.sorted(new MapValuesComp())
.collect(Collectors.toMap(
MapValues::getKey, MapValues::getStdns,
(e1, e2) -> e1,
LinkedHashMap::new));
public class CustomMapSorting {
public static void main(String[] args) throws ParseException {
Map<String, List<Student>> map = new HashMap<>();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
// Class1 Stundent1
Date s1Date1 = format.parse("02/11/2010");
Date s1Date2 = format.parse("02/09/2010");
Date[] s1absentDates = { s1Date1, s1Date2 };
Student s1 = new Student("Student1", Arrays.asList(s1absentDates));
// Class1 Stundent2
Date s2Date1 = format.parse("02/10/2010");
Date[] s2absentDates = { s2Date1 };
Student s2 = new Student("Student2", Arrays.asList(s2absentDates));
// Class2 Stundent3
Date s3Date1 = format.parse("02/12/2010");
Date[] s3absentDates = { s3Date1 };
Student s3 = new Student("Student3", Arrays.asList(s3absentDates));
// Class3 Stundent4
Student s4 = new Student("Stundent4", null);
List<Student> class1SundLst = Arrays.asList(s1, s2);
map.put("Class1", class1SundLst);
map.put("Class2", Arrays.asList(s3));
map.put("Class3", Arrays.asList(s4));
Map<String, List<Student>> newmap = map.entrySet()
.stream()
.map(e -> new MapValues(e.getKey(), e.getValue()))
.sorted(new MapValuesComp())
.collect(Collectors.toMap(MapValues::getKey, MapValues::getStdns, (e1, e2) -> e1, LinkedHashMap::new));
//Printing the sorted values
newmap.entrySet().stream().forEach(e -> System.out.println(e.getKey() + " : " + e.getValue().get(0).absentDates));
}
}
class MapValues {
String key;
List<Student> stdns;
public MapValues(String key, List<Student> stdns) {
super();
this.key = key;
this.stdns = stdns;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<Student> getStdns() {
return stdns;
}
public void setStdns(List<Student> stdns) {
this.stdns = stdns;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return key;
}
}
class MapValuesComp implements Comparator<MapValues> {
public int compare(MapValues o1, MapValues o2) {
if (o1.stdns.get(0).absentDates == null) {
return (o2.stdns.get(0).absentDates == null) ? 0 : 1;
}
if (o2.stdns.get(0).absentDates == null) {
return 1;
}
return o2.stdns.get(0).absentDates.get(0).compareTo(o1.stdns.get(0).absentDates.get(0));
}
}
class Student {
String name;
List<Date> absentDates;
public Student(String name, List<Date> absentDates) {
super();
this.name = name;
this.absentDates = absentDates;
}
#Override
public String toString() {
if (absentDates == null)
return null;
SimpleDateFormat format = new SimpleDateFormat("dd/mm/YYYY");
return format.format(absentDates.get(0));
}
}
I tried a inline solution using lambdas from the answer posted using #Rono. Just a improved version of his solution.
Map<String, List<Student>> res = map.entrySet()
.stream()
.sorted((o1, o2) -> {
if (o1.getValue().get(0).absentDates == null) {
return (o2.getValue().get(0).absentDates == null) ? 0 : 1;
}
if (o2.getValue().get(0).absentDates == null) {
return 1;
}
return o2.getValue().get(0).absentDates.get(0).compareTo(o1.getValue().get(0).absentDates.get(0));
}).
collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,(e1, e2) -> e1,
LinkedHashMap::new));
There is a hashmap and below is the requirement :
Map<String, Object> objectmetainfo = new HashMap();
objectmetainfo.put("userdetails.info.metadata.user.home.address.details", "address");
objectmetainfo.put("userdetails.info.metadata.user.id", "id");
objectmetainfo.put("userdetails.info.metadata.userSupervisor.id", "id");
objectmetainfo.put("info.metadata.code", "code");
objectmetainfo.put("zip", "zip");
Get all the records of hashmap and iterate it
Split the Key based on delimiter and convert it to Pair or Hashmap
The number of delimiter will vary in each string
Below should be the output :
E.g.: For "userdetails.info.metadata.user.home.address.details", "address", below output is required
HashMap<userdetails, HashMap<info, HashMap<metadata, HashMap<user, HashMap<home, HashMap<address, Map<details, address>>>>>>>
or Pair<String, Object> pair = new Pair("userdetails", new Pair("info", new Pair("metadata", new Pair("user", new Pair("home", new Pair("address", new Pair("details", "addressvalue")))))));
Assuming your string won't be crazy long this would work, otherwise you'd get a StackOverflow error.l
I did this using a recursive approach
Split keys by "."
Convert them to the list iterator
Iterate this list recursively to create a nested map
At the end of recursion put the value from objectmetainfo map.
Create an empty result map and recursively merge all the results.
Code:
import java.util.*;
public Map<String, Object> nestedMaps(Iterator<String> keys, String value) {
if (keys.hasNext()) {
String key = keys.next();
Map<String, Object> nestMap = nestedMaps(keys, value);
Map<String, Object> map = new HashMap<>();
map.put(key, nestMap);
if (Objects.equals(nestMap, null))
map.put(key, value);
return map;
}
return null;
}
public void mergeNested(Object srcObj, Object targetObj) {
if (srcObj instanceof Map && targetObj instanceof Map) {
Map<String, Object> srcMap = (Map<String, Object>) srcObj;
Map<String, Object> targetMap = (Map<String, Object>) targetObj;
for (String targetKey : targetMap.keySet()) {
if (srcMap.containsKey(targetKey)) {
mergeNested(srcMap.get(targetKey), targetMap.get(targetKey));
} else {
srcMap.putAll(targetMap);
}
}
}
}
public Map<String, Object> objectmetainfo = new LinkedHashMap<>();
objectmetainfo.put("userdetails.info.metadata.user.home.address.details", "addressValue");
objectmetainfo.put("userdetails.info.metadata.user.id", "id");
objectmetainfo.put("userdetails.info.metadata.userSupervisor.id", "id");
objectmetainfo.put("info.metadata.code", "code");
objectmetainfo.put("zip", "zip");
public Map<String, Object> result = new HashMap<>();
for (Map.Entry<String, Object> e : objectmetainfo.entrySet()) {
List<String> keys = new ArrayList<>(Arrays.asList(e.getKey().split("\\.")));
Map<String, Object> nestedMaps = nestedMaps(keys.iterator(), String.valueOf(e.getValue()));
mergeNested(result, nestedMaps);
}
System.out.println(result);
I printed out all the hashmaps using toString method.
Output:
{
zip= zip,
userdetails= {
info= {
metadata= {
userSupervisor= {
id= id
},
user= {
id= id,
home= {
address= {
details= addressValue
}
}
}
}
}
},
info= {
metadata= {
code= code
}
}
}
Below is the modified logic to remove 2nd recursive call, with this method we are passing the objMap as reference and finally we will have the objMap ready with result
Map<String, Object> objMap = new HashMap<>();
for (Map.Entry<String, Object> e : getObjectMetaInfoMap().entrySet()) {
populateMetaDataMap(keys.iterator(), String.valueOf(e.getValue()), objMap, true, StringUtils.EMPTY);
}
public static Map<String, Object> populateMetaDataMap(Iterator<String> keys, String value, Map<String, Object> objMap, boolean newCall, String matchingKey) {
if (keys.hasNext()) {
String key = keys.next();
if(objMap.get(key) != null && objMap.get(key) instanceof Map) {
return populateMetaDataMap(keys, value, (Map<String, Object>) objMap.get(key), newCall, matchingKey );
} else {
if(newCall) {
newCall = false;
matchingKey = key;
}
Map<String, Object> nestMap = populateMetaDataMap(keys, value, objMap, newCall, matchingKey);
Map<String, Object> map = new HashMap<>();
if (Objects.equals(nestMap, null))
map.put(key, value);
else
map.put(key, nestMap);
if(key.equals(matchingKey)) {
if(Objects.equals(nestMap, null)) {
objMap.put(key, value);
} else {
objMap.put(key, nestMap);
}
}
return map;
}
}
return null;
}
I am a beginner to regex.
I have below String:
fail:2,success:1,fetch:1
Output Map: Get Map which contains all key-values as below:
fail - 2 (key=fail, value=2)
success - 1
fetch - 1
I have tried using below solution:
public static void main(String arg[]) {
String msg = "fail:1,success:1,policyfetch:1";
System.out.println(getKeyValuesFromMsg(msg));
}
public static Map getKeyValuesFromMsg(String msg) {
if (msg != null) {
Map keyvalues = new HashMap();
Pattern p = Pattern.compile("(\\w+):(,+)");
Matcher m = p.matcher(msg);
while (m.find()) {
keyvalues.put(m.group(1), m.group(2));
}
return keyvalues;
} else
return Collections.emptyMap();
}
You can use the split function, The following snippet should work fine
Map<String,String> map = new HashMap();
String str = "fail:2,success:1,fetch:1";
String[] keyValueParts = str.split(",");
for(String s : keyValueParts){
String parts[] = s.split(":");
map.put(parts[0],parts[1]);
}
System.out.println(map);
i would have used below method for the same.
public static void main(String arg[]) {
String msg = "fail:1,success:1,policyfetch:1";
System.out.println(getKeyValuesFromMsg(msg));
}
private static Map<Object, Object> getKeyValuesFromMsg(String msg) {
Map<Object,Object> mapObj = new HashMap<Object,Object>();
for (int i=0;i<msg.split(",").length;i++)
mapObj.put(msg.split(",")[i].split(":")[0],msg.split(",")[i].split(":")[1]);
return mapObj;
}
my solution:
public static Map<String, Integer> trans2Map(String source) {
if (null == source) {
return Collections.emptyMap();
}
Map<String, Integer> result = new HashMap<>();
Arrays.stream(source.split(","))
.filter(pair -> pair.split(":").length == 2)
.forEach(pair -> {
String key = pair.split(":")[0];
Integer value;
try {
value = Integer.parseInt(pair.split(":")[1]);
} catch (Exception e) {
return;
}
result.put(key, value);
});
return result;
}
I have MaterailInfo and StyleInfo, I want to set styleDescription based on StyleNumber matching with materialNumber. I am using 2 for loops, is there any alternative solution?
MaterailInfo:
class MaterailInfo {
private String materialNumber;
private String materialDescription;
public MaterailInfo(String materialNumber, String materialDescription) {
this.materialNumber = materialNumber;
this.materialDescription = materialDescription;
}
// getter setter methods
}
StyleInfo:
class StyleInfo {
private String StyleNumber;
private String styleDescription;
public StyleInfo(String styleNumber, String styleDescription) {
StyleNumber = styleNumber;
this.styleDescription = styleDescription;
}
// getter setter toString methods
}
TEst12:
public class TEst12 {
public static void main(String[] args) {
List<MaterailInfo> mList = new ArrayList<MaterailInfo>();
mList.add(new MaterailInfo("a", "a-desc"));
mList.add(new MaterailInfo("b", "b-desc"));
mList.add(new MaterailInfo("c", "c-desc"));
List<StyleInfo> sList = new ArrayList<StyleInfo>();
sList.add(new StyleInfo("a", ""));
sList.add(new StyleInfo("b", ""));
sList.add(new StyleInfo("c", ""));
for (MaterailInfo m : mList) {
for (StyleInfo s : sList) {
if (s.getStyleNumber().equals(m.getMaterialNumber())) {
s.setStyleDescription(m.getMaterialDescription());
}
}
}
System.out.println(sList);
}
}
If you use a Map instead of a List to store your data, you can get away with doing only a single loop:
Map<String, String> mMap = new HashMap<String, String>();
mMap.put("a", "a-desc");
mMap.put("b", "b-desc");
mMap.put("c", "c-desc");
Map<String, String> sMap = new HashMap<String, String>();
sMap.put("a", "");
sMap.put("b", "");
sMap.put("c", "");
for (Map.Entry<String, String> entry : mMap.entrySet()) {
sMap.put(entry.getKey(), mMap.get(entry.getKey());
}
This code will leave the style description empty if the style number does not match any known material number.
If your numbers can't have duplicates, using a HashMap instead of classes can be a bit faster.
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
public class Demo {
public static void main(String[] args) {
HashMap<String, String> mList = new HashMap();
HashMap<String, String> sList = new HashMap();
mList.put("a", "a-desc");
mList.put("b", "b-desc");
mList.put("c", "c-desc");
sList.put("a", "");
sList.put("b", "");
sList.put("c", "");
Iterator entries = sList.entrySet().iterator();
while (entries.hasNext()) {
Entry entry = (Entry) entries.next();
if (mList.containsKey(entry.getKey())) {
sList.put((String) entry.getKey(), mList.get(entry.getKey()));
}
}
for (Map.Entry<String, String> entry : sList.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
You can do this using one for loop like this
for (int i = 0; i < mList.size(); i++) {
sList.get(i).setStyleDescription(mList.get(i).getMaterialDescription());
}
Note: i am assuming you have balanced lists in term of size.