Java-Collections, cannot overwrite old value with new value - java
I got a question regarding Java-Collections. I iterate through a Java-Collection and if an if-clause is true, I want to change the entry of the Collection. Within the if-clause body the new Value is accepted, but if I want to print the whole collection later, it prints out again the Collection with the old value.
Here the Code:
public boolean checkConsumeStorageCapacity(Multimap<String, Values> mm1, Multimap<String, Values> mm2)
{
boolean enoughStorageCapacity = false;
Multimap<String, Values> mmApp = mm1;
Multimap<String, Values> mmHW = mm2;
Collection<Values> colA = mmApp.get("Storage");
Collection<Values> colH = mmHW.get("Memory");
for (Values vA2 : colA) {
for (Values vH2 : colH) {
if (vA2.getName().equals("Size") && vH2.getName().equals("Size")) {
float StoSize = Float.parseFloat(vA2.getValue());
float MemSize = Float.parseFloat(vH2.getValue());
float maintainableStoSize = StoSize * maintainabilityfactor;
if (MemSize >= maintainableStoSize) {
MemSize -= maintainableStoSize;
vH2.setValue(String.valueOf(MemSize));
String s = vH2.getValue();
System.out.println(s);
enoughStorageCapacity = true;
return enoughStorageCapacity;
}
break;
}
}
}
System.out.println(colH);
Values is a object containing 3 String. The getters/setters are all declared correctly. Printing out s gives the correct value, but printing out colH gives again the old value. Isnt setting the new Value enough, do I additionally have to commit anything in the Collection?
Thanks a lot in advance.
edit:
here the values class, for further understanding.
public class Values {
private String name;
private String type;
private String value;
public Values(String name, String type, String value)
{
this.name = name;
this.type = type;
this.value = value;
}
public String getName()
{
return name;
}
public String getType()
{
return type;
}
public String getValue()
{
return value;
}
public void setName(String name)
{
this.name = name;
}
public void setValue(String value)
{
this.value = value;
}
public void setType(String type)
{
this.type = type;
}
#Override
public String toString() {
return "name=" + name + ", type=" + type + ", value=" + value;
}
}
Another way of dealing with such pointer issues is to initialize a second collection before the loop. As you iterate through add the values that you want to stay the same to the collection and then in the if statement add the changed value/object. This costs a little more memory but no real performance loss
Something like this:
list<T> originallist;
list<T> tmp = new list
for(x : originalList)
{
if(condition)
{
//do things
tmp.add(changedValue)
}
else
{
tmp.add(x)
}
}
Related
Stuck on getting total count and count of certain elements of an array
I'm trying to create two methods in the LineUp class, one method called totalMembers in which it would return the total number of members and another one called totalKinds doing the same thing but returning the number of different kinds of acts. Here is the code for the Act class in which it creates a program for managing a musical festival (sort of) public class Act { private int num_members; private String name; private String kind; private String stage; public Act(int num_members, String name, String kind, String stage) { this.num_members = num_members; this.name = name; this.kind = kind; this.stage = stage; } public Act(int num_members, String name, String kind) { this.num_members = num_members; this.name = name; this.kind = kind; stage = null; } public int getNum_members() { return num_members; } public void setNum_members(int num_members) { this.num_members = num_members; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getKind() { return kind; } public void setKind(String kind) { this.kind = kind; } public String getStage() { return stage; } public void setStage(String stage) { this.stage = stage; } public String toString() { return "(" + num_members + ", " + name + ", " + kind + ", " + stage + ")"; } } The class LineUp represents these acts and here is the code for it thus far. I was thinking of using a for loop to get the number of members for each act however as it's not a 2D array it's much harder to do. For getting the different kinds of acts I have no clue. If anyone could put me in the right direction that would be great. import java.util.Arrays; public class LineUp { private Act[] acts; private int number; private int memberSum; public LineUp() { acts = new Act[30]; number = 0; memberSum = 0; } public int numberOfActs() { return number; } public int totalMembers() { for(int i=0; i < acts.length; i++) { } return memberSum; } public int totalKinds() { } public void addAct(Act a) { if(number == 30) System.out.println("The festival is full!"); else { acts[number] = a; number++; } } public String toString() { return acts + ""; } public void Print() { System.out.println(Arrays.toString(acts)); } }
To properly model Acts you must use actors. No, just kidding, sorry for that one. You have rather many different possibilities evaluating the content of your act[]. A brute, archaic version would go like this public int totalKinds() { List<String> unique = new ArrayList<>(); for (int i = 0; i < acts.length; i++) { if (!unique.contains(acts[i])) unique.add(acts[i].getKind()); } return unique.size(); } E.g. you could use enhanced for loops and exploit the fact, that a set has unique elements: public int totalKinds() { Set<String> unique = new HashSet<>(); for (Act a: acts) { unique.add(a.getKind()); } return unique.size(); } Certainly the most flexible and convenient way is to use the stream api, introduced with Java 8. It really pays off to get acquainted with it. Note that count() returns a Long, while you want int, so there's a conversion needed. public int totalKinds() { long count = Arrays.asList(acts).stream() .map(act -> act.getKind()) .distinct() .count(); return Math.toIntExact(count); }
Iterate over heterogeneous list
I have a method which returns the list like public List<Object> getSomeData(SomeBean sb) { List<Object> data = Lists.newArrayList(); data.add(sb.getId()); // Id->long data.add(sb.getName()); // name->String ..... return data; } and Now I have to iterate over this list, which I have to check type every time as for (int i = 0; i < data.size(); i++) { if (data.get(i) instanceof String) { //append } if (data.get(i) instanceof Long) { //append } .... } I need to append the elements of list in the loop. Are their any better way to achieve this, may be without using instanceof operator.
You should create a class for that data and return an instance of it instead of a List. class SomeEntity { long id; String name; public SomeEntity(long id, String name) { this.id = id; this.name = name; } public long getId() { return id; } public String getName() { return name; } #Overrides public String toString() { return id + " " + name; } } Just use it in your code: public SomeEntity getSomeData(SomeBean sb) { SomeEntity entity = new SomeEntity(sb.getId(), sb.getName()); return entity; } Edit: you can override the toString() method of the class and use it in your code (added above)
Here you go: final List<Object> someData = new ArrayList<>(); someData.add("stringValue"); //String someData.add(1L); //Long Value final String result = someData.stream() .map(String::valueOf) .collect(Collectors.joining(" ")); System.out.println(result);
Random access a value from Java HashMap, when using a custom class object as key for HashMap?
I am using a custom class object as the key for a HashMap. In this class definition, I have overridden the equals() and hashCode() methods. public class TimeTableDataModel { Map <Course, List <Timings>> tm; TimeTableDataModel() { tm = new HashMap<>(); } void addCourseItem(Course course) { tm.put(course, new ArrayList<Timings>()); } void addNewTimeTableItem(Course course, Timings newTiming) { List <Timings> t; if(!tm.containsKey(course)) { addCourseItem(course); } t = tm.get(course); t.add(newTiming); tm.put(course, t); } public static final class Course { private final String courseCode; private final String courseName; private final String section; private final String group; Course(String code, String courseName, String section, String group) { this.courseCode = code; this.courseName = courseName; this.section = section; this.group = group; } public String getCourseCode() { return courseCode; } public String getCourseName() { return courseName; } public String getSection() { return section; } public String getGroup() { return group; } #Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Course)) { return false; } Course otherObj = (Course) obj; return Objects.equals(courseCode,otherObj.courseCode) && Objects.equals(courseName, otherObj.courseName) && Objects.equals(section, otherObj.section) && Objects.equals(group, otherObj.group); } #Override public int hashCode() { return Objects.hash(courseCode, courseName, section, group); } } public static class Timings { String time; String day; String room; Timings(String time, String day) { setTime(time); setDay(day); } public String getTime() { return time; } public String getday() { return day; } public void setTime(String time) { this.time = time; } public void setDay(String day){this.day = day;} } } In above code I have created Course class to be used as the key for the HashMap and using a List<Timings> for values. What I intend is to get a List of timings when a Course is passed to hm.get(course). So far I can get a keyset then sequentially get values for each course. for(Course c : timetable.tm.keySet()) { System.out.println(c.getCourseCode() + " " + c.getCourseName()); for(Timings t : timetable.tm.get(c)) { System.out.println(t.time + " " +t.room + " "+ t.day); } }; Here's the code that populates the HashMap static TimeTableDataModel timetable = new TimeTableDataModel(); Course course = new Course(courseCode,null,section,group); Timings dt = new Timings(time, getDayOfWeek(i)); dt.room = roomNo; timetable.addNewTimeTableItem(course, dt); So to get the timings for a particular course I have to traverse the whole HashMap until the desired course Key is found. What I want is a way to distinguish between each course object contained in the HashMap Key, so I can get Timings for any random course without traversing the whole KeySet. Thanks in advance. Please ask if somethings is unclear in code
Problem what I see here is if(!tm.containsKey(course)){ addCourseItem(course); } and if (this == obj) { return true; } because you are comparing the object. Since both are same class objects equals will always return true and map concludes it as duplicate key.
Jackson Can not deserialize empty array
Im reading the Facebook Insights and trying to get Jackson to map the JSON to Object. If all the data comes in without empty, i have it working. But Im having a problem trying to deserialize empty array of key value. Even after trying this post: How to prevent null values inside a Map and null fields inside a bean from getting serialized through Jackson it did not resolve the problem :( This is the JSON : {"data":[{"id":"492640667465465\/insights\/page_fans_country\/lifetime","name":"page_fans_country","period":"lifetime","values":[{"value":{"MY":26315,"ID":311,"SG":77,"NP":63,"MM":56,"PH":51,"GB":44,"US":44,"KR":36,"TH":36,"IN":34,"BD":24,"PK":22,"BN":22,"AU":15,"TW":14,"VN":12,"KH":11,"YE":11,"CA":10,"JP":10,"EG":8,"ZA":7,"SA":6,"ES":6,"HK":6,"FR":6,"IT":5,"IL":5,"IR":5,"NG":5,"LK":5,"BR":5,"IQ":4,"AF":4,"AE":4,"GT":4,"RO":4,"LR":4,"RU":4,"PS":4,"DE":4,"CN":4,"LY":3,"JO":3},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":26326,"ID":315,"SG":77,"NP":63,"MM":56,"PH":54,"GB":44,"US":43,"TH":38,"KR":36,"IN":33,"BD":23,"BN":22,"PK":21,"AU":16,"TW":14,"VN":12,"KH":11,"YE":11,"CA":10,"JP":10,"EG":8,"ZA":7,"SA":7,"ES":6,"HK":6,"FR":6,"IT":5,"IL":5,"IR":5,"NG":5,"LK":5,"BR":5,"IQ":4,"RU":4,"CN":4,"GT":4,"RO":4,"LR":4,"AF":4,"PS":4,"DE":4,"AE":4,"LY":3,"CH":3},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":26338,"ID":312,"SG":79,"NP":63,"MM":55,"PH":52,"US":45,"GB":44,"TH":39,"KR":34,"IN":32,"BD":24,"BN":22,"PK":21,"AU":16,"TW":14,"KH":12,"VN":12,"CA":11,"YE":11,"JP":10,"EG":8,"ZA":7,"SA":7,"ES":6,"HK":6,"FR":6,"IT":5,"CN":5,"IR":5,"NG":5,"LK":5,"BR":5,"IL":5,"IQ":4,"AF":4,"AE":4,"GT":4,"RO":4,"LR":4,"RU":4,"PS":4,"DE":4,"NZ":3,"TR":3},"end_time":"2014-08-04T07:00:00+0000"}],"title":"Lifetime Likes by Country","description":"Lifetime: Aggregated Facebook location data, sorted by country, about the people who like your Page. (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/day","name":"page_storytellers_by_country","period":"day","values":[{"value":[],"end_time":"2014-08-02T07:00:00+0000"},{"value":[],"end_time":"2014-08-03T07:00:00+0000"},{"value":[],"end_time":"2014-08-04T07:00:00+0000"}],"title":"Daily Country: People Talking About This","description":"Daily: The number of People Talking About the Page by user country (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/week","name":"page_storytellers_by_country","period":"week","values":[{"value":{"MY":136,"IN":3,"ID":2,"BD":1,"US":1,"TN":1,"AU":1},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":131,"IN":3,"US":1,"TN":1,"AU":1,"ID":1},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":118,"IN":2,"KH":1,"TR":1,"US":1,"TN":1,"AR":1,"AU":1},"end_time":"2014-08-04T07:00:00+0000"}],"title":"Weekly Country: People Talking About This","description":"Weekly: The number of People Talking About the Page by user country (Unique Users)"},{"id":"492640667465465\/insights\/page_storytellers_by_country\/days_28","name":"page_storytellers_by_country","period":"days_28","values":[{"value":{"MY":492,"IN":5,"ID":3,"AU":2,"SG":2,"ZA":2,"US":2,"GB":2,"RO":1,"PH":1,"NP":1,"BD":1,"JO":1,"PS":1,"TN":1,"IR":1,"CA":1,"CN":1,"KR":1},"end_time":"2014-08-02T07:00:00+0000"},{"value":{"MY":499,"IN":5,"ID":3,"GB":2,"SG":2,"ZA":2,"US":2,"RO":1,"PH":1,"NP":1,"BD":1,"AU":1,"CN":1,"KR":1,"TN":1,"IR":1,"CA":1,"JO":1},"end_time":"2014-08-03T07:00:00+0000"},{"value":{"MY":501,"IN":4,"ID":3,"SG":2,"ZA":2,"US":2,"GB":2,"AU":1,"RO":1,"PH":1,"NP":1,"JO":1,"AR":1,"KR":1,"BD":1,"TR":1,"IR":1,"CA":1,"CN":1,"KH":1,"TN":1},"end_time":"2014-08-04T07:00:00+0000"}],"title":"28 Days Country: People Talking About This","description":"28 Days: The number of People Talking About the Page by user country (Unique Users)"}],"paging":{"previous":"https:\/\/graph.facebook.com\/v2.0\/492640667465465\/insights?since=1406649169&until=1406908369","next":"https:\/\/graph.facebook.com\/v2.0\/492640667465465\/insights?since=1407167569&until=1407426769"}} My current code does not like this at all --> "value":[] And the follwing is my Object: import java.util.Date; import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; public class Insights { private Data[] data; private Paging paging; public Data[] getData() { return data; } public void setData(Data[] data) { this.data = data; } public Paging getPaging() { return paging; } public void setPaging(Paging paging) { this.paging = paging; } /** * inner class for Data * #author pohsoon.yap * */ public static class Data { private String id; private String name; private String period; private Values[] values; private String title; private String description; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPeriod() { return period; } public void setPeriod(String period) { this.period = period; } public Values[] getValues() { return values; } public void setValues(Values[] values) { this.values = values; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } /** * inner class for Values * #author pohsoon.yap * */ public static class Values { // if "value":[] then this will break private Map<String, Integer> Value; private String end_time; public Map<String, Integer> getValue() { return Value; } public void setValue(Map<String, Integer> value) { Value = value; } public String getEnd_time() { return end_time; } public void setEnd_time(String end_time) { this.end_time = end_time; } } } public static class Paging { private String previous; private String next; public String getPrevious() { return previous; } public void setPrevious(String previous) { this.previous = previous; } public String getNext() { return next; } public void setNext(String next) { this.next = next; } } } My code snippet as follows: ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); List<Insights> insightList = new ArrayList(); String insightStr = ""; try { for (Operation operation : mq.getOperationList()){ String apiEndPoint = this.facebookGraphApiUrl + operation.getApi(); apiEndPoint = apiEndPoint.replace("{pageid}", mq.getFacebookPage().getPageId()); uri = new URI(apiEndPoint); insightStr = facebook.getApi().restOperations().getForObject(uri, String.class); Insights insights = mapper.readValue(insightStr, Insights.class); The full stack trace: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token at [Source: java.io.StringReader#625a80df; line: 1, column: 1603] (through reference chain: com.social.facebook.model.Insights["data"]->com.social.facebook.model.Data["values"]->com.social.facebook.model.Values["value"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599) at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593) at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:306) at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:147) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:18) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)
As explained by others, you are trying to map JSON Array into Java Map, something that is not allowed by default. But it may be possible to allow empty JSON Array to map to java.util.Map. by enabling DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT: objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT); this at least works in case of a POJO type; I do not recall if this works for other Java types that usually take JSON Object.
The value field in your model is declared as Map while the corresponding JSON property can be either an empty array or a key-value map. Jackson cannot assign an empty array to a map field. Assuming that you wish to solve the problem on the client side, you can modify the setValue method to accept a generic Object and then verify whether it is a map or an array (actually List since Jackson deserialize arrays as Java collections). Here is an example: public class JacksonArrayAsMap { public static class Bean { private Map<String, Object> value; public void setValue(Object value) { if (value instanceof Map) { this.value = (Map<String, Object>) value; } else if (value instanceof List && ((List) value).size() == 0){ this.value = Collections.EMPTY_MAP; } else { throw new IllegalArgumentException("Invalid value: " + value); } } #Override public String toString() { return "Bean{" + "value=" + value + '}'; } } public static void main(String[] args) throws IOException { final String json1 = "{\"value\":{}}"; final String json2 = "{\"value\":[]}"; final String json3 = "{\"value\":{\"a\":\"b\"}}"; ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.readValue(json1, Bean.class)); System.out.println(mapper.readValue(json2, Bean.class)); System.out.println(mapper.readValue(json3, Bean.class)); } } Output: Bean{value={}} Bean{value={}} Bean{value={a=b}}
Converting javascript key value pair object to a java key value pair.
I have a javascript array containing an object which represents a key value pair. I'm trying to convert this javascript object into a java object. Could someone assist me? Thanks in advance. Javascript var array = []; for (var i = 0; i < filterIdArray.length; i++) { array.push({name:filterIdArray[i], value:$("#" + filterIdArray[i]).val()}); } params["t:array"] = array; Java #RequestParameter(value = "t:array", allowBlank = true) String array List<String> inputs = null; if(array != null) { inputs = Arrays.asList(array); } Java Object representing key value pair public class Test { private String name; private String value; public Test() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }