Sort Apache Commons MultiValuedMap by Key - java

I would like to know how to sort Apache Commons MultiValuedMap by Key. The below is the key class used.
public class VssKey implements Comparable<VssKey> {
private String funCode;
private String varntCode;
private String itemNb;
public VssKey(SummaryDataOracle summaryDataOracle) {
this.funCode = summaryDataOracle.getFuncCode();
this.varntCode = summaryDataOracle.getVariantCd();
this.itemNb = summaryDataOracle.getItemNB();
}
public String getFunCode() {
return funCode;
}
public void setFunCode(String funCode) {
this.funCode = funCode;
}
public String getVarntCode() {
return varntCode;
}
public void setVarntCode(String varntCode) {
this.varntCode = varntCode;
}
public String getItemNb() {
return itemNb;
}
public void setItemNb(String itemNb) {
this.itemNb = itemNb;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((funCode == null) ? 0 : funCode.hashCode());
result = prime * result + ((itemNb == null) ? 0 : itemNb.hashCode());
result = prime * result + ((varntCode == null) ? 0 : varntCode.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VssKey other = (VssKey)obj;
if (funCode == null) {
if (other.funCode != null)
return false;
} else if (!funCode.equals(other.funCode))
return false;
if (itemNb == null) {
if (other.itemNb != null)
return false;
} else if (!itemNb.equals(other.itemNb))
return false;
if (varntCode == null) {
if (other.varntCode != null)
return false;
} else if (!varntCode.equals(other.varntCode))
return false;
return true;
}
#Override
public String toString() {
return String.format("VssKey [funCode=%s, varntCode=%s, itemNb=%s]", funCode, varntCode, itemNb);
}
#Override
public int compareTo(VssKey o) {
int k1 = Integer.parseInt(this.varntCode);
int k2 = Integer.parseInt(o.getVarntCode());
return k2 - k1;
}
}
The below map is constructed by iterating SummerDataOracle values. The values are pushed into the map by VssKey object as shown below.
MultiValuedMap<VssKey, String> partNumberVarientMap = new ArrayListValuedHashMap<>();
for (SummaryDataOracle summaryDataOracle : summeryDataOracleList) {
VssKey key = new VssKey(summaryDataOracle);
String varntText = null;
if (!StringUtils.isEmpty(summaryDataOracle.getVariantSmText())) {
varntText = summaryDataOracle.getVariantSmText().trim();
}
partNumberVarientMap.put(key, varntText);
}
I need to achieve the order in the Map.
Thanks

HashMap/MultivaluedHashMap cannot be sorted directly.
Better, to get its key and sort them and parse map in sorted order.
Map<String, List<String>> map = new MultivaluedHashMap<>();
map.put("b", new ArrayList<>());
map.put("a", new ArrayList<>());
List<String> keylist = new ArrayList<>(map.keySet());
Collections.sort(keylist);
for(String key : keylist) {
System.out.println(key + " : " + map.get(key));
}

By design, you can't sort a HashMap. If you need to keep a specific order in your map, it is recommended to use a Map implementation like TreeMap.
What you can do if you want to iterate over a HashMap in a specific order, is getting the keys and sort them. Then you can iterate over the keys and lookup your values accordingly:
HashMap<String, List<String>> map = new HashMap<>();
for(String key : new TreeSet<String>(map.keySet())){
map.get(key);
}

Related

Append generated json tree

I would like to ask you for help. I have a Device object
public class Device {
public String name;
public String deviceId;
#JsonSerialize(using = CustomResourceSerializer.class)
public Map<String, Map<String, Object>> customResources;
}
My goal is to "extract" this map directly to Device Object. Firstly I used #JsonAnyGetter which worked well and Map was nested under field String of first map directly under Device object.
But I need more complex logic and I have two problems which I don't know how to solve.
Key of first map is for example "configuration/inputOne". With #JsonAnyGetter the example output is { "configuration/inputOne": { "rate":23 } }
What I need is nested structure based on delimiter, so
{ "configuration": { "inputOne": { "rate":23 } } }
This I was almost able to do easily with custom JsonSerializer
jsonGenerator.writeStartObject();
foreach(splited key)
jsonGenerator.writeObjectFieldStart(resourceUriItem);
foreach(value)
jsonGenerator.writeObjectField(k, v);
foreach(splitted key)
jsonGenerator.writeEndObject();
jsonGenerator.writeEndObject();
But final object looks like
{ "customResource": {"configuration": { "inputOne": { "rate":23 } } } }
CustomResource field is from Device object and I don't know how to get rid of it. As with JsonAnyGetter. That's the first problem.
As you see, I am splitting the key of the map to have more nested strucutre, so from the "configuration/inputOne" to { configuration { inputOne { .. } }. But the map customResources can have of course multiple items, so for example:
"configuration/inputOne"
"configuration/inputTwo"
"configuration"
Now you probably see where is the problem. As I am iterating over keys and I am creating nested structure, I will override it. So for example, firstly I will create object configuration, then inputOne and fill it with fields. Closing objects. Then second item in map, creating configuration object and inputTwo object. But with creation of configuration, I will delete the one previously created with inputOne.
Do you have any proposal how to solve this? Thanks.
You can turn your map into a type of a tree by splitting on the / and creating a parent child relationship on the split items.
Using the following class as a tree element / node.
class TreeElement {
private String key;
private Object value;
private List<TreeElement> children;
public TreeElement(String key) {
this.key = key;
}
// getters and setters here
public void addChild(TreeElement child) {
if (this.children == null) {
this.children = new ArrayList<TreeElement>();
}
this.children.add(child);
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((key == null) ? 0 : key.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TreeElement other = (TreeElement) obj;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equalsIgnoreCase(other.key))
return false;
return true;
}
#Override
public String toString() {
return "TreeElement [key=" + key + ", value=" + value + ", children=" + children + "]";
}
}
And the following test code.
public static void main(String[] args) {
try {
// create the config1, config2, etc.. here
Device device1 = new Device();
device1.customResources = new HashMap<String, Map<String, Object>>();
device1.customResources.put("configuration/inputOne", config1);
device1.customResources.put("configuration/inputTwo", config2);
device1.customResources.put("configuration", config3);
device1.customResources.put("configuration", duplicateConfig3);
device1.customResources.put("otherConfig", otherConfig);
device1.customResources.put("thirdConfig1", thirdConfig1);
device1.customResources.put("thirdConfig1/inputOne", thirdConfig2);
device1.customResources.put("thirdConfig1/inputOne", duplicateThirdConfig2);
List<TreeElement> elements = new ArrayList<TreeElement>();
for (Map.Entry<String, Map<String, Object>> entry : device1.customResources.entrySet()) {
TreeElement element = generateElement(null, entry.getKey(), entry.getValue());
elements.add(element);
}
List<TreeElement> joinedElements = joinElements(elements);
for (TreeElement e : joinedElements) {
System.out.println(e.getKey() + " - " + e.getValue());
if (e.getChildren() != null) {
for (TreeElement c : e.getChildren()) {
System.out.println("\t" + c.getKey() + " - " + c.getValue());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
This method generates a TreeElement from a Map> variable.
private static TreeElement generateElement(TreeElement parent, String item, Map<String, Object> value) {
try {
List<String> tokens = new ArrayList<String>(Arrays.asList(item.split("/")));
TreeElement child = new TreeElement(tokens.get(0));
boolean parentWasNull = false;
if (parent == null) {
parent = child;
parentWasNull = true;
}
if (tokens.size() > 1) {
if (parentWasNull == false) {
parent.addChild(child);
}
tokens.remove(0);
generateElement(child, StringUtils.join(tokens, "/"), value);
} else {
child.setValue(value);
if (parentWasNull == false) {
parent.addChild(child);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return parent;
}
This method joins common TreeElement objects into one parent and multiple children.
private static List<TreeElement> joinElements(List<TreeElement> elements) {
List<TreeElement> joinedElements = new ArrayList<TreeElement>();
for (TreeElement element : elements) {
if (joinedElements.contains(element) == true) {
// joined elment does not have children
if (joinedElements.get(joinedElements.indexOf(element)).getChildren() == null) {
joinedElements.get(joinedElements.indexOf(element)).setChildren(element.getChildren());
} else {
//joined element has children and the current element also has children
if (element.getChildren() != null) {
joinedElements.get(joinedElements.indexOf(element)).getChildren().addAll(element.getChildren());
}
}
/*
* set the value of joined element to the value of the current element; will overwrite
* any existing value if duplicates exist
*/
if (element.getValue() != null) {
joinedElements.get(joinedElements.indexOf(element)).setValue(element.getValue());
}
} else {
joinedElements.add(element);
}
}
return joinedElements;
}
I'm not sure how efficient this code is, but you get the below output which you can traverse in your custom serializer to print to JSON.
thirdConfig1 - {rate=30}
inputOne - {rate=3020}
configuration - {rate=1200}
inputOne - {rate=23}
inputTwo - {rate=50}
otherConfig - {rate=10}

How I can remove and update sorted elements in TreeSet?

I have some entity class
class Data{
private String quoteID;
private String bidOrOffer;
private float price;
private long volume;
private Date createDate;
public Data(String quoteID, String bidOrOffer, float price, long volume) {
this.quoteID = quoteID;
this.bidOrOffer = bidOrOffer;
this.price = price;
this.volume = volume;
createDate = new Date();
}
#Override
public int hashCode() {
int hash = 5;
hash = 13 * hash + Objects.hashCode(this.quoteID);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Data other = (Data) obj;
if (!Objects.equals(this.quoteID, other.quoteID)) {
return false;
}
return true;
}
}
and I push some elements into TreeSet whit special order
Comparator<Data> offerOrder = (Data o1, Data o2) -> {
if(o1.equals(o2))
return 0;
if(o1.getPrice() == o2.getPrice()
&& o1.getVolume() == o2.getVolume()){
return o1.getCreateDate().after(o2.getCreateDate())? 1:-1;
}
if(o1.getPrice() == o2.getPrice()){
return o1.getVolume() > o2.getVolume()? 1:-1;
}
if(o1.getPrice() > o2.getPrice())
return 1;
else
return -1;
};
Set<Data> treeSet = new TreeSet<>(offerOrder);
treeSet.add(new Data("Q1", "OFFER", 1.32f, 1000000));
treeSet.add(new Data("Q6", "OFFER", 1.32f, 1000000));
treeSet.add(new Data("Q7", "OFFER", 1.33f, 200000));
The main goal of this task it is remove and update some data by quoteID
but if I do this
treeSet.contains(new Data("Q7", "OFFER", 0, 0)); //return false
thereafter method remove doesn't work too.
Any ideas?
While inserting "Q7" the comparator returns 1 in compare to "Q1".
If you now want to remove "Q7" with new Data("Q7", "OFFER", 0, 0) the comparator returns -1.
So the child of the "wrong" path of the tree compared next.
treeSet.contains(new Data("Q7", "OFFER", 2, 0)) would return true (compare to "Q1" returns 1).
You should take care of change the implementation of your Comparator<Data> offerOrder because that implementation does not permit to find the object you're looking for with treeSet.contains.
For example in your case:
Comparator<Data> offerOrder = (Data o1, Data o2) -> {
return o1.quoteID.compareTo(o2.quoteID);
};
And then returns true:
treeSet.contains(new Data("Q7", "OFFER", 0, 0)); //return true
There is also an error in your equals method:
final Quote other = (Quote) obj;
if (!Objects.equals(this.quoteID, other.quoteID)) {
return false;
}
You should use:
if (!this.quoteID.equals(other.quoteID)) {
return false;
}
And given that quoteID is a String is not clear what is the Quote class.
I suggest to change use hashCode and equals methods in this way:
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((quoteID == null) ? 0 : quoteID.hashCode());
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Data other = (Data) obj;
if (quoteID == null) {
if (other.quoteID != null)
return false;
} else if (!quoteID.equals(other.quoteID))
return false;
return true;
}
You cannot search "quoteID" as is inside Data object. You have to iterate each Data object and match for "quoteID".
Iterator<Data> iterator = treeSet.iterator();
while(iterator.hasNext()){
Data dataobj = iterator.next();
String qID = dataobj.quoteID;
if(qID.equals("Q7")){
//write your code.
}
}

How to do iterative sorting in string arraylist?

I have an arraylist with below string elements -->
['STM-1000-H', 'STM-2000-E', 'STM-4000-H', 'STM-200-H', 'SFP-1000-A',
'SFP-300-H', 'SAFPX-1000-H', 'SAFPX-2000-A', 'STM-1000-H-L1', 'STM-1000-H-L1+VA+GH', 'STM-1000-H-L2']
I want an arraylist with grouping like ...
display STM- 400, 500, 600, 100, 2000, 4000 (in that order), followed by SPX- 1000, 2000, 4000 (in that order, then followed by the SAFPX- 1000. Also, I have to list each by the L, L1, L2, M, M1, M2, M3, H, H! and VH (in that Order).
Can you please assist with this, Array list is string elements only.
You should create a custom comparator and then use that to sort the arraylist.
For example (this does some of the sorting you asked for but is not checked for edge-cases, that is up to you to fix). Note: Java 8 is used
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("STM-1000-H");
list.add("STM-2000-E");
list.add("SAFPX-1000-H-L2");
list.add("SAFPX-1000-H-L1");
list.add("STM-1000-H-L1");
list.add("SFP-1000-B");
list.add("SFP-1000-A");
HashMap hm = new HashMap();
hm.put("STM", 1);
hm.put("SFP", 2);
hm.put("SAFPX", 3);
list = sort(list, hm);
for (String s : list) {
System.out.println(s);
}
}
public static ArrayList<String> sort(ArrayList<String> list, HashMap<String, Integer> hashmap) {
Comparator<String> comparator = (string1, string2) ->
{
String[] tokens1 = string1.split("-");
String[] tokens2 = string2.split("-");
if (hashmap.get(tokens1[0]) > hashmap.get(tokens2[0]))
return 1;
else if (hashmap.get(tokens1[0]) < hashmap.get(tokens2[0]))
return -1;
if (Integer.parseInt(tokens1[1]) > Integer.parseInt(tokens2[1]))
return 1;
else if (Integer.parseInt(tokens1[1]) < Integer.parseInt(tokens2[1]))
return -1;
if (tokens1.length > 2 && tokens2.length > 2) {
int res = tokens1[2].compareTo(tokens2[2]);
if(res != 0)
return res;
}
if (tokens1.length > 3 && tokens2.length > 3) {
int res = tokens1[3].compareTo(tokens2[3]);
if(res != 0)
return res;
}
return 0;
};
Collections.sort(list, comparator);
return list;
}
Outputs:
STM-1000-H
STM-1000-H-L1
STM-2000-E
SFP-1000-A
SFP-1000-B
SAFPX-1000-H-L1
SAFPX-1000-H-L2
Stream.of("STM-1000-H",
"STM-2000-E",
"STM-4000-H",
"STM-200-H",
"SFP-1000-A",
"SFP-300-H",
"SAFPX-1000-H",
"SAFPX-2000-A",
"STM-1000-H-L1",
"STM-1000-H-L1+VA+GH",
"STM-1000-H-L2")
.collect(Collectors.groupingBy(s -> s.substring(0, s.indexOf('-'))))
.entrySet()
.stream()
.sorted((e1, e2) -> -e1.getKey().compareTo(e2.getKey()))
.forEach(e -> {
System.out.println(e.getKey() + ":");
e.getValue().stream().sorted().forEach(System.out::println);
});
--
STM:
STM-1000-H
STM-1000-H-L1
STM-1000-H-L1+VA+GH
STM-1000-H-L2
STM-200-H
STM-2000-E
STM-4000-H
SFP:
SFP-1000-A
SFP-300-H
SAFPX:
SAFPX-1000-H
SAFPX-2000-A
package com.skadakov.examples.devrev;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
/**
*
* #author s.kadakov
*/
public class DevRev {
private final String series;
private final int model;
private final String version;
private final String revision;
public DevRev(String firmware) {
String[] ss = firmware.split("-");
if (ss.length < 3) {
throw new IllegalArgumentException(firmware);
}
this.series = ss[0];
this.model = Integer.parseInt(ss[1]);
this.version = ss[2];
this.revision = ss.length == 3 ? null : ss[3];
}
public String getSeries() {
return series;
}
public int getModel() {
return model;
}
public String getVersion() {
return version;
}
public String getRevision() {
return revision;
}
#Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.series);
hash = 97 * hash + this.model;
hash = 97 * hash + Objects.hashCode(this.version);
hash = 97 * hash + Objects.hashCode(this.revision);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DevRev other = (DevRev) obj;
if (this.model != other.model) {
return false;
}
if (!Objects.equals(this.series, other.series)) {
return false;
}
if (!Objects.equals(this.version, other.version)) {
return false;
}
return Objects.equals(this.revision, other.revision);
}
#Override
public String toString() {
return series + "-" + model + "-" + version + (revision != null ? "-" + revision : "");
}
public static void main(String[] args) {
String[] firmare = {
"STM-1000-H",
"STM-2000-E",
"STM-4000-H",
"STM-200-H",
"SFP-1000-A",
"SFP-300-H",
"SAFPX-1000-H",
"SAFPX-2000-A",
"STM-1000-H-L1",
"STM-1000-H-L1+VA+GH",
"STM-1000-H-L2"};
Map<String, List<DevRev>> revs = new TreeMap<>();
for (String f : firmare) {
DevRev dr = new DevRev(f);
List<DevRev> sdevs = revs.get(dr.getSeries());
if (sdevs == null) {
sdevs = new ArrayList<>();
revs.put(dr.getSeries(), sdevs);
}
sdevs.add(dr);
}
for (Map.Entry<String, List<DevRev>> entry : revs.entrySet()) {
String series = entry.getKey();
List<DevRev> devices = entry.getValue();
System.out.println(series);
devices.sort(new Comparator<DevRev>() {
#Override
public int compare(DevRev o1, DevRev o2) {
return new Integer(o1.getModel()).compareTo(o2.getModel());
}
});
for (DevRev dr : devices) {
System.out.println("-> " + dr);
}
}
}
}

Backup of HashMap's Maps in Java

I want to do a backup copy of a Map (that contains other Maps).
I have something like this:
Map<TYPE1, Map<TYPE2, TYPE3>>
TYPE1, TYPE2 and TYPE3 are objects from 3 different classes created by me (e.g the components of that classes are: String, Integer, Double,....)
I tried
Map<TYPE1, Map<TYPE2, TYPE3>> Map2= new HashMap<TYPE1, Map<TYPE2, TYPE3>>(Map1)
[....make some changings in Map1...]
Map1 = new HashMap<TYPE1, Map<TYPE2, TYPE3>>(Map2)
Map1 is the original Map I want to make a copy of.
I also tried PutAll method but it didn't work (the content of the Map isn't the same of the original one).
Do you know other methods? Thank you.
Since the key and value in your collection are your self define class.
Those content int the map are not really copied but share the same instance of your "TYPE".
You need to do something like this to copy the value from all the content.
This is just a very simple example, so there's no any encapsulation.
public class Foo1 {
public Integer a = 0;
public Foo1() {
}
public Foo1(Integer a) {
this.a = a;
}
public Foo1 clone() {
return new Foo1();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
public class Foo2 {
public Integer a = 0;
public Foo2() {
}
public Foo2(Integer a) {
this.a = a;
}
public Foo2 clone() {
return new Foo2();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
public class Foo3 {
public Integer a = 0;
public Foo3() {
}
public Foo3(Integer a) {
this.a = a;
}
public Foo3 clone() {
return new Foo3();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((a == null) ? 0 : a.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Foo1 other = (Foo1) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
return true;
}
}
Copy your value by your own.
Map<Foo1, Map<Foo2, Foo3>> map1 = new HashMap<Foo1, Map<Foo2, Foo3>>();
Map<Foo1, Map<Foo2, Foo3>> map2 = new HashMap<Foo1, Map<Foo2, Foo3>>();
Map<Foo2, Foo3> tmp = new HashMap<Foo2, Foo3>();
tmp.put(foo.new Foo2(), foo.new Foo3());
map1.put(foo.new Foo1(), tmp);
for (Foo1 key : map1.keySet()) {
Map<Foo2, Foo3> tmp2 = new HashMap<>();
for (Foo2 key2 : map1.get(key).keySet()) {
tmp2.put(key2.clone(), map1.get(key).get(key2).clone());
}
map2.put(key, tmp2);
}
for (Foo1 key : map1.keySet()) {
for (Foo2 key2 : map1.get(key).keySet()) {
map1.get(key).get(key2).a = 10;//change map1's value
}
}
for (Foo1 key : map2.keySet()) {
for (Foo2 key2 : map2.get(key).keySet()) {
System.out.println(map2.get(key).get(key2).a);// the value in map2 still 0
}
}
very interesting article about deep copy:
How do you make a deep copy of an object in Java?
with serialization/deserialization, you dont need to go inside your classes,
and you dont forget some variable.
it gives:
Map<Integer, Map<String,String>> mimss =new HashMap<Integer, Map<String,String>>();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(mimss);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
Map<Integer, Map<String,String>> mimss_copy=(Map<Integer, Map<String,String>>) new ObjectInputStream(bais).readObject();
You can also convert to B64 in the middle if you want to save it in text:
String serial= DatatypeConverter.printBase64Binary(byteData);
byte[] byteData_reverse=DatatypeConverter.parseBase64Binary(serial);
REQUIREMENT: TYPE1, TYPE2, TYPE3 must be serializable
to be serializable, your class must be like that
public class myclass implements Serializable
and you should (not mandatory) declare inside
private static final long serialVersionUID = 6569838532917408380L;
If anything inside in serializable too, it's OK (standard types are, collections, ...)

Avoiding repetition (for loop)

I'm making a program that use two text files (two tables), and perform basic relational algebra (Union, difference, intersection,and join) on them. I'm using a Hashmaps, to save the values (keys/values) each time, but I wonder how can I use one main "for loop" instead of 4 for each operation.
This is my code:
for (Map.Entry<Integer, String> htEntries : map.entrySet()) {
if(map2.containsKey(htEntries.getKey()) && map2.get(htEntries.getKey()).equals(htEntries.getValue())){
inter.put( htEntries.getKey(), htEntries.getValue());
}
}
for (Map.Entry<Integer, String> joinEntries : map.entrySet()) {
if(map2.containsKey(joinEntries.getKey())){
join.put( joinEntries.getKey(), joinEntries.getValue());
}
}
for (Map.Entry<Integer, String> diffEntries : map.entrySet()) {
if(!map2.containsKey(diffEntries.getKey())){
diff.put( diffEntries.getKey(), diffEntries.getValue());
}
}
for (Map.Entry<Integer, String> diffEntries2 : map2.entrySet()) {
if(!map.containsKey(diffEntries2.getKey())){
diff2.put( diffEntries2.getKey(), diffEntries2.getValue());
}
}
I think you must use a least 2 for loops, you can do this:
for (Map.Entry<Integer, String> htEntries : map.entrySet()) {
if(map2.containsKey(htEntries.getKey()) {
join.put( htEntries.getKey(), htEntries.getValue());
if (map2.get(htEntries.getKey()).equals(htEntries.getValue())) {
inter.put(htEntries.getKey(), htEntries.getValue());
}
} else {
diff.put( htEntries.getKey(), htEntries.getValue());
}
}
for (Map.Entry<Integer, String> diffEntries2 : map2.entrySet()) {
if(!map.containsKey(diffEntries2.getKey())){
diff2.put(diffEntries2.getKey(), diffEntries2.getValue());
}
}
You can still do set/value pairs with sets:
Set<SetEntry> setA = new HashSet<>();
setA.add(new SetEntry("a", 1));
setA.add(new SetEntry("b", 2));
setA.add(new SetEntry("c", 2));
setA.add(new SetEntry("d", 1));
Set<SetEntry> setB = new HashSet<>();
setB.add(new SetEntry("a", 1));
setB.add(new SetEntry("b", 2));
setB.add(new SetEntry("e", 1));
setB.add(new SetEntry("f", 2));
Set<SetEntry> union = new HashSet<>(setA);
union.addAll(setB);
System.out.println("Union: " + union);
Set<SetEntry> intersection = new HashSet<>(setA);
intersection.retainAll(setB);
System.out.println("Intersection: " + intersection);
Set<SetEntry> difference = new HashSet<>(setA);
difference.removeAll(setB);
System.out.println("Difference: " + difference);
Here is the output:
Union: [a->1, b->2, c->2, d->1, e->1, f->2]
Intersection: [a->1, b->2]
Difference: [c->2, d->1]
Here is a base SetEntry implementation:
private class SetEntry {
private final String key;
private final int value;
public SetEntry(String key, int value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public int getValue() {
return value;
}
// Just use the key for equality
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SetEntry setEntry = (SetEntry) o;
return key.equals(setEntry.key);
}
#Override
public int hashCode() {
return key.hashCode();
}
#Override
public String toString() {
return key+"->"+value;
}

Categories

Resources