I have a tree map with a following key value pair combination
Map is declared as follows
Map<String, List<Bean>> outputMap = new TreeMap<String,List<Bean>>();
Corresponding code will be
for (String course_date : shiftSet) {
Bean courseBean = null;
boolean valueExists = false;
for (Entry<String, List<Bean>> entry: courseMap.entrySet()){
valueExists = false;
String studentDetail = entry.getKey();
String [] studentSet = StringUtils.getArray(studentDetail , ",");
String studentId = studentSet[0];
String courseId = studentSet[1];
for(Bean resultBean : entry.getValue()){
if(course_date.equalsIgnoreCase(resultBean.getCourseDate()){
valueExists = true;
}
}
if(!valueExists ) {
courseBean = new Bean();
courseBean.setStudent(studentId);
courseBean.setCourse(courseId);
List<Bean> courseList = entry.getValue();
courseList.add(courseBean);
outputMap.put(studentId+courseId, courseList);
}
}
}
And finally the OutputMap needs to be inserted to courseMap
OutputMap result will be
{ADV001,STU02=
[Bean[course_id=ADV1, student_id=STU1_2,Day=Wed-Night,courseDate=12-Feb-2014],
Bean[course_id=ADV1, student_id=STU1_2,Day=Tue-Day,courseDate=11-Feb-2014],
Bean[course_id=ADV1, student_id=STU1_2,Day=Tue-Night,courseDate=11-Feb-2014],
Bean[course_id=ADV1, student_id=STU1_2,Day=Wed-Day,courseDate=12-Feb-2014]]
So Here i need to sort the outputMap based on courseDate?Kindly help on how the desired output can be achieved ?
Thanks in advance..
A TreeMap sorts the elements by their key, if courseDate is part of the values, you'd have to use a TreeSet, e.g.
import java.util.Set;
import java.util.TreeSet;
public class Example {
public static void main(String[] args) {
Set<Dummy> example = new TreeSet<>();
example.add( new Dummy(7, "first dummy"));
example.add( new Dummy(2, "second dummy"));
example.add( new Dummy(3, "third dummy"));
System.out.println(example);
}
static class Dummy implements Comparable<Dummy>{
int courseDate;
String name;
Dummy(int courseDate, String name) {
this.courseDate = courseDate;
this.name = name;
}
#Override
public String toString() {
return String.format("[Dummy courseDate=%s, name=%s]", courseDate, name);
}
#Override
public int compareTo(Dummy o) {
// here you specify how the TreeSet will order your elements
return Integer.compare(this.courseDate, o.courseDate);
}
}
}
Related
Both Key and value are user input.
Then value is passed to the as variable to retrieve the corresponding key for the value.
My output returns NULL. Please guide me to retrieve key by passing value.
public class DomainBO {
private Map<String,String> domainMap;
public Map<String,String> getDomainMap() {
return domainMap;
}
public void setDomainMap(Map<String,String> domainMap) {
this.domainMap = domainMap;
}
//This method should add the domainName as key and their ipAddress as value into a Map
public void addDNSDetails (String domainName,String ipAddress){
domainMap.put(domainName, ipAddress);
}
/*
* This method should return the domain name for the specific ipAddress which is passed as the argument.
* For example: If the map contains the key and value as:
* www.yahoo.net 205.16.214.15
www.gmail.net 195.116.254.154
www.tech.net 15.160.204.105
if the ipAddress is 195.116.254.154 the output should be www.gmail.net
*/
public String findDomainName(String ipAddress)
{
String domain = null;
for (Map.Entry<String, String> entry : domainMap.entrySet()) {
String k = entry.getKey();
String v = ipAddress;
if (k.equals(v)) {
domain = k;
}
}
return domain;
}
}
You actually compare the key to your ipAdress that's what you want, rather it's :
public String findDomainName(String ipAddress) {
String domain = null;
for (Map.Entry<String, String> entry : domainMap.entrySet()) {
String k = entry.getKey();
String v = entry.getValue(); // <----
if (ipAddress.equals(v)) {
domain = k;
}
}
return domain;
}
Can be shorten in
public String findDomainName(String ipAddress) {
for (Map.Entry<String, String> entry : domainMap.entrySet())
if (ipAddress.equals(entry.getValue()))
return entry.getKey();
return null;
}
Using Streams
public String findDomainName(String ipAddress) {
return domainMap.entrySet().stream().filter(e -> ipAddress.equals(e.getValue()))
.map(Map.Entry::getKey).findFirst().orElse(null);
}
btw : First code returns last match, second code return first match
I know this question will be pretty amateur but, I having trouble understanding why my hashmap will not store or retrieve values when I use the same object instance as a key. My code is as follows
public class Candidate {
private String id;
private String name;
public Candidate (String id, String name){
this.id = id;
this.name = name;
}
public static void main(String args[]){
Candidate cad = new Candidate("101","hari");
HashMap<Candidate,String> mp = new HashMap<Candidate,String>();
mp.put(cad, "sachin");
mp.put(cad, "shewag");
for(Candidate cand : mp.keySet()){
System.out.println(mp.get(cand).toString());
}
}
I am overriding hashcode and equals as follows.
#Override
public boolean equals(Object obj){
Candidate cad =(Candidate)obj;
if(!(obj instanceof Candidate)){
return false;
}
if(cad.id.equals(this.id) && cad.name.equals(this.name)){
return true;
}
return false;
}
#Override
public int hashCode(){
return Objects.hash(id, name);
}
When I try to get the size of the hashmap, it returns as only one. meaning the first insertion into the hashmap was overridden by the second one.
Is it because I am using the same instance of Candidate to insert two values? Is it possible to force hashmap to insert both key,value pairs?
The whole idea behind a Map is that 1) keys are unique -- it holds only one key/value pair for a particular key, and 2) its look up is relatively "cheap".
You've only got one object within your HashMap. Understand that when you add another key, value pair to the map, if the key is the same as a previous item in the map, the previous item is replaced by the new one. If you want to add two or more items, then use different keys, or create a Map that holds a List<...> of objects as its value. e.g.,
HashMap<Candidate, List<String>>
In this situation, you would first check to see if the Map holds a Candidate item, and if so, add a new String to its list. If not, then add the new Candidate with a new ArrayList<String> value. Usually I use a method for just this purpose, something like:
public static void put(Candidate cand, String text) {
if (newMap.containsKey(cand)) {
newMap.get(cand).add(text);
} else {
List<String> list = new ArrayList<>();
list.add(text);
newMap.put(cand, list);
}
}
And yes, as d.j.brown states in comment, fix your equals method to avoid a class cast exception.
Something like so:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class MyCandidateTest {
private static Map<Candidate, List<String>> newMap = new HashMap<>();
public static void main(String args[]) {
Candidate cad = new Candidate("101", "hari");
put(cad, "Foo");
put(cad, "Bar");
for (Candidate cand : newMap.keySet()) {
System.out.println(newMap.get(cand).toString());
}
}
public static void put(Candidate cand, String text) {
if (newMap.containsKey(cand)) {
newMap.get(cand).add(text);
} else {
List<String> list = new ArrayList<>();
list.add(text);
newMap.put(cand, list);
}
}
}
public class Candidate {
private String id;
private String name;
public Candidate(String id, String name) {
this.id = id;
this.name = name;
}
#Override
public boolean equals(Object obj) {
// Candidate cad =(Candidate)obj; // !! no
if (!(obj instanceof Candidate)) {
return false;
}
Candidate cad = (Candidate) obj; // !! yes
if (cad.id.equals(this.id) && cad.name.equals(this.name)) {
return true;
}
return false;
}
#Override
public int hashCode() {
return Objects.hash(id, name);
}
}
There is a simpler way to do what you want with java-8 btw, simplified example:
HashMap<String, List<String>> mp = new HashMap<>();
List<String> list = Arrays.asList("aa", "aa", "bb", "bb");
for (String s : list) {
mp.computeIfAbsent(s, k -> new ArrayList<>()).add("c");
}
System.out.println(mp); // {bb=[c, c], aa=[c, c]}
Either use
Map<Candidate, List<String>> or
A good 3rd party alternative such as Google's Multimap: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html
I've created a DataGrid so:
DataGrid<String> grid = new DataGrid<String>();
grid.setPageSize(4);
TextColumn<String> date = new TextColumn<String>() {
public String getValue(String object) {
return object;
}
};
grid.addColumn(date, "Date");
TextColumn<String> time = new TextColumn<String>() {
public String getValue(String object) {
return object;
}
};
grid.addColumn(time, "Time");
TextColumn<String> number = new TextColumn<String>() {
public String getValue(String object) {
return object;
}
};
grid.addColumn(number, "Number");
Now I'd like to populate it but I don't understood how to do it because I have these String[] and they must be splitted also:
textString[1]="01/01/2014;10:00;300";
textString[2]="02/02/2014;11:00;400"; ...
Thanks in advance.
UPDATE
#Sturmination I followed your hint but there is another problem for this code(assuming that splitting is done):
..
protected static List<Example> EXAMPLES = null;
..
public void method() {
...
EXAMPLES = Arrays.asList(new Example("01/01/2014", "10:00", "300"));
grid.setRowCount(EXAMPLES.size(), true);
grid.setRowData(0, EXAMPLES);
..
}
It returns this error:
The method setRowData(int, List<? extends String>) in the type AbstractHasData<String> is not applicable for the arguments (int, List<Example>)
And it suggests : Change type of EXAMPLES to List<? extends String> but it doesn't work anyway.
Have you tried this:
DataGrid<String> grid = new DataGrid<String>();
grid.setPageSize(4);
TextColumn<String> date = new TextColumn<String>() {
public String getValue(String object) {
return object.split(';')[0];
}
};
grid.addColumn(date, "Date");
TextColumn<String> time = new TextColumn<String>() {
public String getValue(String object) {
return object.split(';')[1];
}
};
grid.addColumn(time, "Time");
TextColumn<String> number = new TextColumn<String>() {
public String getValue(String object) {
return object.split(';')[2];
}
};
grid.addColumn(number, "Number");
A nicer approach would be to create a new Java Bean for your rows and convert your String[] items to a List<Row> of the new row objects
You can use String[] in your code:
DataGrid<String> grid = new DataGrid<String>();
TextColumn<String[]> date = new TextColumn<String[]>() {
public String getValue(String[] object) {
return object[0];
}
};
Split your strings when you add them:
private ListDataProvider<String[]> dataProvider = new ListDataProvider<String[]>();
private List<String[]> displayItems = dataProvider.getList();
...
for (String textString : textStrings) {
displayItems.add(textString.split(";");
}
I would do it like this, if size of you data is not huge.
Create a class
Class YourClass{
private String date, time, number;
public YourClass(String date, String time, String nuber){
this.date=date;
this.time=time;
this.number=number;
}
//getters and setters here
}
Create a method to conver you values
private List<YourObject> convert(String[] values){
List<YourClass> data= new ArrayList<YourClass>();
String date, time, number;
for(i=0; values.size(); i++){
values[i] //split the string and asign values to date, time and number
dataList.add(new YourClass(date, time, number));
}
return dataList;
}
Add you values to DataGrid
ListDataProvider<YourClass> provider= new ListDataProvider<YourClass>();
List<YourClass> dataList = new ArrayList<YourClass>();
dataList.addAll(convert(textString[]));
provider.addDataDisplay(grid);
provider.setList(dataList);
Then in your Columns just:
return object.getDate();
return object.getTime();
return object.getNumber();
I wanted to create a table/list in Java, and I wonder what is the best way to handle it.
The table should have a structure like this:
Term propertyList entitiesList
a1 p1=1, p2=2, p3=2 T1,T2
a2 p5=0, p4=5 ,p3=3 T2,T1
a3 p1=1 ,p4=3, p3=9 T3,T1,T2
...
a10
I have a list with exactly 10 terms, and for every term there is a list of properties (deep with key and value), and the properties can be either in one or more entities.
I need some help on how to create it, e.g. should I use list, map, collection etc.
How can I add hardcoded values to them as literals in the code, and what is the best way to read data from it, taking into account performance, given that later I will need to use this for every entity and find the related properties that participate in every term.
first off Create Term class.
So you have list of Terms: List<Term>
Term class
public class Term {
private String mName = "";
private Map<String, Integer> mPropertyMap = new LinkedHashMap<String, Integer>();
private List<String> mEntitiesList = new ArrayList<String>();
public Term(String name) {
mName = name;
}
public void generate(Map<String, Integer> propertyMap, List<String> entitiesList) {
mPropertyMap = propertyMap;
mEntitiesList = entitiesList;
}
public Map<String, Integer> getPropertyMap() {
return mPropertyMap;
}
public void setPropertyMap(Map<String, Integer> propertyMap) {
this.mPropertyMap = propertyMap;
}
public List<String> getEntitiesList() {
return mEntitiesList;
}
public void setEntitiesList(List<String> entitiesList) {
this.mEntitiesList = entitiesList;
}
public String getName() {
return mName;
}
public void setmName(String name) {
this.mName = name;
}
}
Main Class
public class MyClass {
private List<Term> mTermList = null;
private void init() {
mTermList = new ArrayList<Term>();
}
private void addSomeTerm() {
Map<String, Integer> propertyMap = new LinkedHashMap<String, Integer>();
propertyMap.put("p1", 1);
propertyMap.put("p2", 2);
propertyMap.put("p3", 3);
List<String> entitiesList = new ArrayList<String>();
entitiesList.add("T1");
entitiesList.add("T2");
Term term = new Term("a1");
term.generate(propertyMap, entitiesList);
mTermList.add(term);
}
private String printTerms() {
StringBuilder buff = new StringBuilder();
for(Term currTerm : mTermList){
buff.append(currTerm.getName()).append(" ");
Map<String, Integer> propertyMap = currTerm.getPropertyMap();
Set<String> sets = propertyMap.keySet();
Iterator<String> itr = sets.iterator();
String key = null;
Integer value = null;
while(itr.hasNext()){
key = itr.next();
value = propertyMap.get(key);
buff.append(key + "=" + value).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
buff.append(" ");
List<String> entitiesList = currTerm.getEntitiesList();
for(String str : entitiesList){
buff.append(str).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
}
return buff.toString();
}
/**
* #param args
*/
public static void main(String[] args) {
MyClass m = new MyClass();
m.init();
m.addSomeTerm();
System.out.println(m.printTerms());
}
}
Output:
a1 p1=1,p2=2,p3=3 T1,T2
It looks like you could have the following structure:
class Term {
String id;
Map<String, String> properties;
List<Entity> entities; // (or Set<Entity> if no duplicates are allowed)
}
But it's not very clear what you mean by "deep" and by "the properties can be either in one or more entities".
I have a TreeMap that maps String keys to a custom City class. Here is how it is instantiated:
TreeMap<String, City> nameDictionary = new TreeMap<String, City>(new CityNameComparator());
CityNameComparator implementation:
public class CityNameComparator implements Comparator<String>
{
public int compare (String c1, String c2) {
return c1.compareTo(c2);
}
}
I have a method that returns an iterator that should iterate through the map in key-ascii order:
public Iterator<City> getNameIterator(){
return nameDictionary.values().iterator();
}
For some reason the values are returned in the order they were added to the TreeMap. Any ideas?
It works just fine:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeMap;
public class test2 {
public static class City {
public final String m_name;
public City(String aName) {
m_name = aName;
}
}
public static class CityNameComparator implements Comparator<String>
{
public int compare (String c1, String c2) {
return c1.compareTo(c2);
}
}
public static class CityMap {
TreeMap<String, City> nameDictionary = new TreeMap<String, City>(new CityNameComparator());
public Iterator<City> getNameIterator(){
return nameDictionary.values().iterator();
}
public City put(String aName) {
return nameDictionary.put(aName, new City(aName));
}
}
public static void main(String[] args) {
CityMap cityMap = new CityMap();
cityMap.put("d");
cityMap.put("b");
cityMap.put("c");
cityMap.put("a");
for (Iterator<City> cities = cityMap.getNameIterator(); cities.hasNext(); ) {
City city = cities.next();
System.out.println(city.m_name);
}
}
}
Output:
a
b
c
d
Are you sure a LinkedHashMap hasn't been assigned to the Map reference by mistake? That would preserve the order the entries were added to the map.
Or perhaps there is a bug in the code that is adding entries, putting the wrong value with a key.
Iterate over the entries, and see what is in the map:
for (Map.Entry<String, City> e : dictionary.entrySet())
System.out.println(e.getKey() + " --> " + e.getValue());
Sorry, stupid bug. I was assigning a different iterator based on a bug somewhere else. It works fine now.