Remove Duplicates from ArrayList filled with POJOs - java

I have an ArrayList filled POJOs and I want to remove all POJOs, which have a duplicate variable. This is the POJO:
public static class UrlStore {
public String url;
public String data;
public UrlStore(String url) {
this.url = url;
}
public void setData(String data) {
this.data = data;
}
}
My way to remove duplicate "url"-variables in the ArrayList<UrlStore> is to iterate through the list and to remove those duplicates. It was said to me that I could simply use a Set to do this, but I can't figure out how to use it with an ArrayList containing POJOs. Or do you have even a better way?
Thanks for any suggestions!

You can override the equals() and hashCode() methods in your POJO and pass the List<UrlStore> to the Set.
List<UrlStore> listOfUrlStore = ......
Set<UrlStore> foo = new HashSet<UrlStore>(listOfUrlStore);
I have used a simple HashSet here , the correct implementation of Set depends on your requirement. You can even convert the Set back to the List .
listOfUrlStore.clear();
listOfUrlStore.addAll(foo);

package test.urlstore;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class DuplicateDemo{
public static void main(String[] args) throws Exception {
List<UrlStore> urlStores = new ArrayList<UrlStore>();
UrlStore usg = new UrlStore("google");
UrlStore usy = new UrlStore("yahoo");
UrlStore usb = new UrlStore("bing");
UrlStore usa = new UrlStore("ask");
UrlStore usd = new UrlStore("duckduckgo");
usg.setData("mail");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("search");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("doc");
urlStores.add(usg);
usg = new UrlStore("google");
usg.setData("search");
urlStores.add(usg);
usg = new UrlStore("google");
usy.setData("search");
urlStores.add(usy);
usy.setData("search");
urlStores.add(usy);
usb.setData("search");
urlStores.add(usb);
usb.setData("search");
urlStores.add(usb);
usa.setData("search");
urlStores.add(usa);
usd.setData("search");
urlStores.add(usd);
System.out.println("before removing duplicates");
// before removing duplicates
for (Iterator iterator = urlStores.iterator(); iterator.hasNext();) {
UrlStore urlStore = (UrlStore) iterator.next();
System.out.println(urlStore.toString());
}
System.out.println("\n\nafter removing duplicates");
//removing duplicates
Set<UrlStore> uniqueUrlStores = new HashSet<UrlStore>(urlStores);
//After removing duplicates
for (Iterator iterator = uniqueUrlStores.iterator(); iterator.hasNext();) {
UrlStore urlStore = (UrlStore) iterator.next();
System.out.println(urlStore.toString());
}
}
static class UrlStore {
public String url;
public String data;
public UrlStore(String url) {
this.url = url;
}
public void setData(String data) {
this.data = data;
}
#Override
public String toString() {
return "UrlStore [url=" + url + ", data=" + data + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((url == null) ? 0 : url.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;
UrlStore other = (UrlStore) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
}
}
}

Override hashCode() and equals() in your POJO and then:
List<URLStore>() list = //Your list;
Set<URLStore> set =new HashSet<URLStore>(list);

Don't forget to override the equals method of your POJO.
One this is done, you could use contains method of List to check if your object is in the list before add it.
For the Set, you don't have to use it with the list, it replace the list. You can populate a Set from a List with addAll(Collection c)

Related

Sort Apache Commons MultiValuedMap by Key

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);
}

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}

Convert a Tree like List of Strings to xml [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I need to convert these type of strings which are stored in an ArrayList :
Alpha.Beta.Com.
Alpa.Xeta.Hash.
Alpha.Eta.Dot.
Alpha.Eta.Comma.
Alpha.Eta.Dollar.
Alpha.Xeta.Tilde
Alpha.Beta.Com.Xeta.
here Alpha.Beta.Com. will have Xeta as child ,but Xeta must not have Hash and Tilde as children in this object.
Only,Alpha.Xeta object will have Hash and Tilde as children
these strings are like tree like structure(n levels) which means ,Alpha has Beta,Xeta & Eta as Child.
Furthermore,Beta has Com,
Xeta has Hash & Tilde,
Eta has Comma,Dollar & Dot as child.
We need to identify each parent and child using java program and then build it to XML.
Check this:
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class StringsToXmlConverter {
private static final String SEPARTOR = "\\.";
List<String> list;
Map<String, XmlElement> elements = new HashMap<String,XmlElement>();
public StringsToXmlConverter(List<String> list) {
this.list = list;
}
public String getXml() {
for (String xmlPaths: list) {
String[] splitedElements = xmlPaths.split(SEPARTOR);
XmlElement parent = null;
for (String elem : splitedElements) {
XmlElement currentElem = null;
if (elements.containsKey(elem)) {
currentElem = elements.get(elem);
if (parent != null) {
addChild(parent, currentElem);
}
} else {
currentElem = createNewElement(parent, elem);
elements.put(elem, currentElem);
}
parent = currentElem;
}
}
return buildXml().toString();
}
private void addChild(XmlElement parent, XmlElement currentElem) {
currentElem.parent = parent;
parent.childs.add(currentElem);
}
private XmlElement createNewElement(XmlElement parent, String name) {
XmlElement currentElem;
currentElem = new XmlElement();
currentElem.name = name;
if (parent != null) {
addChild(parent, currentElem);
}
return currentElem;
}
private StringBuilder buildXml() {
StringBuilder xml = new StringBuilder();
for(XmlElement elem : elements.values()) {
if (elem.parent == null) {
xml.append(elem.toXml());
}
}
return xml;
}
private class XmlElement {
String name;
Set<XmlElement> childs = new HashSet<XmlElement>();
XmlElement parent = null;
boolean isPrinted = false;
private Set<XmlElement> getNoPrintedChilds() {
Set<XmlElement> notPrintedChilds = new HashSet<XmlElement>();
Iterator<XmlElement> iterator = childs.iterator();
while(iterator.hasNext()) {
XmlElement node = iterator.next();
if (!node.isPrinted) {
notPrintedChilds.add(node);
}
}
return notPrintedChilds;
}
public String toXml() {
StringBuilder xml = new StringBuilder();
if (!isPrinted) {
xml.append("<" + name);
if (getNoPrintedChilds().isEmpty()) {
xml.append("/>");
} else {
xml.append(">");
for (XmlElement elem : getNoPrintedChilds()) {
xml.append(elem.toXml());
}
xml.append("</" + name + ">");
}
}
isPrinted = true;
return xml.toString();
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((name == null) ? 0 : name.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;
XmlElement other = (XmlElement) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
private StringsToXmlConverter getOuterType() {
return StringsToXmlConverter.this;
}
}
public static void main(String[] args) {
List<String> list= Arrays.asList("Alpha.Beta.Com",
"Alpha.Xeta.Hash",
"Alpha.Eta.Dot",
"Alpha.Eta.Comma",
"Alpha.Eta.Dollar",
"Alpha.Xeta.Tilde");
StringsToXmlConverter converter = new StringsToXmlConverter(list);
System.out.println(converter.getXml());
}
}

Sort LinkedHashMap using Comparable based on object attribute

I want to sort a LinkedHashMap based on object attribute and using Comparable. Here is my code:
public class MapClass{
public static void main(String args[]){
sortMapBasedOnValueObjectUsingComprable();
}
public static void sortMapBasedOnValueObjectUsingComprable(){
Map map = new LinkedHashMap();
map.put("2",new Pojo("456"));
map.put("4",new Pojo("366"));
map.put("1",new Pojo("466"));
map.put("8",new Pojo("5666"));
map.put("9",new Pojo("456"));
map.put("3",new Pojo("66"));
// How to sort ...?
Set<Map.Entry<String,Object>> st = map.entrySet();
Iterator itr = st.iterator();
while(itr.hasNext()){
Map.Entry mxt= (Map.Entry)itr.next();
Pojo pj = (Pojo)mxt.getValue();
System.out.println(pj.getX());
}
}
public class Pojo implements Serializable, Comparable<Object>{
private static final long serialVersionUID = 1L;
private String x;
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public Pojo(String x) {
super();
this.x = x;
}
#Override
public int compareTo(Object o) {
return 0;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((x == null) ? 0 : x.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;
Pojo other = (Pojo) obj;
if (x == null) {
if (other.x != null)
return false;
} else if (!x.equals(other.x))
return false;
return true;
}
}
So u need to first dump your entrySet into a List and then sort it.You can't sort a set unless you are using a TreeSet.I will prefer to dump it into a List which implements RandomAccess so that I can fetch any element by its index.
Map<String,Object> map = new LinkedHashMap<>();
Set<Map.Entry<String,Object>> st = map.entrySet();
List<Map.Entry<String,Object>> listSort = new ArrayList<>(st);
Collections.sort(listSort,new Comparator<Map.Entry<String,Object>(){
public int compare(Map.Entry<String,Object> entry1,Map.Entry<String,Object> entry2){
return ((Comparable)entry1.getValue).compareTo(entry2.getValue.compareTo);
});
Just iterate the list and you can get the elements sorted
Note:- I have implemented a Comparator using anonymous inner class and this Comparator in turn uses the Comparable instance of Pojo class

Removing duplicate Sets from List

I am trying to remove duplicate Set of custom objects from ArrayList. Below is the code I have written which uses toString representation of custom EmployeeObj to compare. Can you please suggest what other approaches can be taken?
package com.collections;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DupSetInsideList {
public static void main(String[] args) {
List<Set<EmployeeObj>> list = new ArrayList<Set<EmployeeObj>>();
Set<EmployeeObj> set1 = new HashSet<EmployeeObj>();
Set<EmployeeObj> set2 = new HashSet<EmployeeObj>();
Set<EmployeeObj> set3 = new HashSet<EmployeeObj>();
list.add(set1);
list.add(set2);
list.add(set3);
EmployeeObj empObj1 = new EmployeeObj(1, "Nikhil");
EmployeeObj empObj2 = new EmployeeObj(2, "Rakesh");
EmployeeObj empObj3 = new EmployeeObj(3, "Kunal");
set1.add(empObj1);
set1.add(empObj2);
set2.add(empObj1);
set2.add(empObj2);
set3.add(empObj1);
set3.add(empObj2);
set3.add(empObj3);
System.out.println("List with duplicaes: " + list);
//Output: List with duplicaes: [[1=Nikhil, 2=Rakesh], [1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]]
//Remove duplicates
List<Set<EmployeeObj>> nonDupList = new ArrayList<Set<EmployeeObj>>();
for(Set<EmployeeObj> obj1:list) {
if(!nonDupList.contains(obj1)) {
nonDupList.add(obj1);
}
}
System.out.println("List without duplicates: " + nonDupList);
//List without duplicates: [[1=Nikhil, 2=Rakesh], [3=Kunal, 1=Nikhil, 2=Rakesh]]
}
}
class EmployeeObj {
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
public EmployeeObj(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.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;
EmployeeObj other = (EmployeeObj) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
#Override
public String toString() {
return id + "=" + name;
}
}
If you want a list behaviour guaranteeing a uniqueness of elements use a LinkedHashSet instead of ArrayList.
If you are bound to using ArrayList (as in a student exercise), extend it, overwrite add and addAll methods by checking the uniqueness first and then calling super.add resp. super.addAll and then use the new class in place of ArrayList.
The Set interface specifies the equals method as follows:
Compares the specified object with this set for equality. Returns true if the specified object is also a set, the two sets have the same size, and every member of the specified set is contained in this set (or equivalently, every member of this set is contained in the specified set).
So in order to create a list that contains no duplicates (even if the elements in the list are sets), one can simply write
//Remove duplicates
List<Set<EmployeeObj>> nonDupList =
new ArrayList<Set<EmployeeObj>>(
new LinkedHashSet<Set<EmployeeObj>>(list));
Try this solution:
private boolean equals(Set elements, Set elements2) {
return elements != null && elements.equals(elements2);
}
private List<Set> removeDuplicates(List<Set> from) {
List<Set> noDuplicates = new ArrayList<Set>();
for (Set possibleDuplicate : from) {
boolean alreadyInNoDuplicatesList = false;
for (Set elementFromNoDuplicateList : noDuplicates) {
if (equals(elementFromNoDuplicateList, possibleDuplicate)) {
alreadyInNoDuplicatesList = true;
break;
}
}
if (!alreadyInNoDuplicatesList) {
noDuplicates.add(possibleDuplicate);
}
}
return noDuplicates;
}
Put the Sets in a Set and they'll be removed as if by magic!

Categories

Resources