Iterate through hash maps and object - java

I am gradually learning how to use Hashmaps , I have a map where i would be adding
HashMap( student id, other student records as object() ) .
I am trying to retrieve the values with their keys.
Please see below.
HashMap<String, Object> studentinfo = new HashMap<String, Object>();
List<Object> lstObject = new ArrayList<Object>();
studentinfo.put("student height", 5.01); //Put data in studentinfo hashmap
lstObject.add(studentinfo);
// New items hashmap
HashMap<String, Object> items = new HashMap<String, Object>();
//Put object in items hashmap
items.put("student id 001",lstObject); //Store data for 1st id student with 001
items.put("student id 002",lstObject); //Store data for 2nd id student with 002
for (Map.Entry<String, Object> entry : items.entrySet()) {
if(entry.getKey().equals("student id 001")){
//Get student id for only student id 001
System.out.println(entry.getValue());
// When i print this out , this is what i get
// [{student height=5.01}]
}
}
How can i loop thru to get the value only
Like this, for example:
5.01 // Student id 001

To get the value 5.01 which is stored in a map for the key "student height" within a list that is stored in another map under the key "student id 001", you'll need to code the access to that information. The outer map itself only knows of values and if you define the value type to be Object you'd have to cast yourself.
A better design might be to replace that list with a Student object which has a property height and access that.
But just for information, if you'd define your map like Map<String, List<Map<String, Object>> you'd be able to directly access the lists and their elements as values, e.g. (not handling null for simplicity):
Double height = (Double)items.get("student id 001").get(0).get("student height");
Just to reiterate: this is awkward design and should be changed, you'll probably realize that whith increasing experience and knowledge.
Better:
class Student {
double height;
Student(double h) {
height = h;
}
}
Map<String, Student> students = ...;
students.put("student 001", new Student(5.01) );
double height = students.get("student 001").height;
Note that I left out a lot of code for simplicity reasons such as modifiers, getters/setters, null checks etc.
Another note (added here instead of a comment for formatting reasons):
items.put("student id 001",lstObject); //Store data for 1st id student with 001
items.put("student id 002",lstObject); //Store data for 2nd id student with 002
This will put the same list as the value for both keys, i.e. if you change the list elements you'll change it for both student ids.

Related

How to retrieve value from Map<ArrayList<String>, Object>

I want to know how can I retrieve values from Map<ArrayList<String>, Object> Where the String and object are stored as Array [] for user define length.
Here is an Example:
int counter=0, n=0;
if (dataSnapshot.exists()){
for (DataSnapshot ds: dataSnapshot.getChildren()){
loca[counter]= new ArrayList<>();
itemListProduct[n]= new ItemListProduct();
itemListProduct[n]= ds.getValue(ItemListProduct.class);
loca[counter].add(testHeaderlist.get(counter));
System.out.println(ds.child("item_NAME").getValue(String.class));
objectMap.put(loca[counter],itemListProduct[n]);
counter++;
}
Here the testHeaderlist is an ArrayList<String> where there are some string stored.
I wanted to store data in the below Image manner:
So now my question is how can I retrieve the Key as well as the Object from "dataList". As from the code which I have shared at the TOP "n" number of list, and the object are stored in the dataList.
The thing is that I want to retrieve to use it in ExpandableListView. loca as header and itemListproduct as my value Object. Where the both are stored at objectMap.
Can anyone please solve it. Thank you!
It is permitted but rather atypical to have an ArrayList as a key to a map. To get the Object you need to do the following:
Object val = map.get(arrayList)
Here, arrayList must contain the exact same strings in the same order as the ArrayList key which refers to the desired object.
Example
Map<List<String>, Integer> map = new HashMap<>();
List<String> key = List.of("abc", "efg");
map.put(key, 20);
Integer v = map.get(List.of("efg","abc")); // different key so
// object not found
System.out.println(v); // prints null
v = map.get(List.of("abc", "efg"));
System.out.println(v); // prints 20
You can get all the Keys of a map by doing
Set<List<String>> set = map.keySet();
You also need to readup on HashMap and ArrayList to understand how they work. The following will keep replacing the object for the key of list[0]
dataList.put(list[0], object[0]);
dataList.put(list[0], object[1]);
dataList.put(list[0], object[2]);
dataList.put(list[0], object[3]);
When the above is done, list[0] will only refer to object[3]

Grouping a List by two fields in Java

I have a Student class. It contains the city, name and country fields.I have an ArrayList that contains Student objects. What I want to do is to group student objects with city and country fields. I can do it with one attribute like this
But how can i do both name and country? Do you have any idea? I am using java 7.
for (Student student: studentList) {
Long key = student.country;
if(map.containsKey(key)){
List<Student> list = map.get(key);
list.add(student);
}else{
List<Student> list = new ArrayList<Student>();
list.add(student);
map.put(key, list);
}
}
Use some key type which allows you to support multiple values, for example:
List<Object> key = Arrays.asList(city, country);
Replace your Long key ... line with this (and update map's type accordingly), e.g.
Map<List<Object>, List<Student>> map = new HashMap<>();
(List<Object> is actually not a great choice here, it's merely expedient: I'd use something like a specific CityAndCountry class, defined for example using Google's AutoValue)

Java stream - List of Maps to a reduced List of Maps

I'm looking to convert a List of Maps to another List of Maps which is grouped.
So I have the below list of maps -
List<Map<String, Object>
[{
"accId":"1",
"accName":"TestAcc1",
"accNumber":"101",
"currency":"USD",
"amount":"1000"
},
{
"accId":"1",
"accName":"TestAcc1",
"accNumber":"101",
"currency":"GBP",
"amount":"800"
},
{
"accId":"1",
"accName":"TestAcc1",
"accNumber":"101",
"currency":"EUR",
"amount":"900"
},
{
"accId":"2",
"accName":"TestAcc2",
"accNumber":"102",
"currency":"USD",
"amount":"9000"
},
{
"accId":"2",
"accName":"TestAcc2",
"accNumber":"102",
"currency":"GBP",
"amount":"8000"
},
{
"accId":"2",
"accName":"TestAcc2",
"accNumber":"102",
"currency":"EUR",
"amount":"9500"
}
]
Data table for reference:
accId accName accNumber currency amount
1 TestAcc1 101 USD 1000
1 TestAcc1 101 GBP 800
1 TestAcc1 101 EUR 900
2 TestAcc2 102 USD 9000
2 TestAcc2 102 GBP 8000
2 TestAcc2 102 EUR 9500
I'd like to group the currency + amount for the accounts to something like below:
List<Map<String, Object>
[{
"accId":"1",
"accName":"TestAcc1",
"accNumber":"101",
"currencies":
{
"USD":"1000",
"GBP":"800",
"EUR","900"
}
},
{
"accId":"2",
"accName":"TestAcc2",
"accNumber":"102",
"currencies":
{
"USD":"9000",
"GBP":"8000",
"EUR","9500"
}
}
]
I was wondering how to go about doing this. Can somebody please help me out here?
It's best to make use of composition here - consider creating these kinds of objects:
AccountInfo with account ID, account name and account number (you would need it to have value semantics, i.e. equals and hashCode implemented - see e.g. #EqualsAndHashCode)
AccountBalance with account currency and amount
AccountRecord with an AccountInfo and an AccountBalance
Account with an AccountInfo and a list of AccountBalances
Now what you want to do simplifies to mapping a stream of AccountRecords into a stream of Accounts. This can be achieved by:
Mapping your objects into AccountRecords.
Grouping by AccountInfo.
Constructing an Account from the AccountInfo and a list of AccountRecords.
Example:
Stream<AccountRecord> accountStream = Stream.of(); // your data here
List<Account> accountList = accountStream
.collect(Collectors.groupingBy(AccountRecord::getAccountInfo))
.entrySet().stream()
.map(entry -> new Account(
entry.getKey(),
entry.getValue().stream()
.map(AccountRecord::getAccountBalance)
.collect(Collectors.toList())
))
.collect(Collectors.toList());
General description of method:
You can make a separate currency map: Map currency map = new HashMap<>();
Then you will need an if statement to group your currencies based upon your accId since the currency-map holds all of your currencies with a common accId. You then need to find all your unique Ids, group them and add a currencyMap to them.
Code Example:
Map<String,Map<String,String>> comparisonMap = new HashMap<>();
Map<String,String> currencyMap = new HashMap<>();
for(Map<String,String> myMap:myListOfMaps){
//if we have seen this id before or the currency map is empty
//then put in the newest entry in the currencymap and set the currentId
if (currencyMap.keySet().size() = 0 || myMap.get("aacId").equals(currentId)){
currencyMap.put(myMap.get("currency"),myMap.get("amount"))}
String currentId = myMap.get("aacId")
//if we see a different ID then, record the old id and old currency map, set the
//currentId to the new Id, create a new currencyMap and add in this entry's data
//to the new currencyMap
else {
comparisonMap.put(currentId,currencyMap);
currentId = myMap.get("aacId");
Map<String,String> currencyMap = new HashMap<>();
currencyMap.put(myMap.get("currency"),myMap.get("amount"));
}
}
new Map<String,Object> Accountmap = new HashMap<>();
new ArrayList<Map<String,Object>> finalList = new ArrayList<>();
}
//loop through your original list and seperate out individual unique accounts.
for(Map<String,String> myMap:myListOfMaps){
//if the accountmap is empty, fill in the first account you see
if(Accountmap.get("aacID") == null &&
Accountmap.get("aacName") == null &&
Accountmap.get("aacNumber") == null){
Accountmap.put("aacID",myMap.get("aacID"));
Accountmap.put("aacName",myMap.get("aacName"));
Accountmap.put("aacNumber",myMap.get("aacNumber"));
}
//if the account info you see next is different than what you have, add the
//account info you have now to the final list and create a new Accountmap
//to hold the newest data we are seeing now.
else if(!(Accountmap.get("aacID").equals(myMap.get("aacID")) &&
Accountmap.get("aacName").equals(myMap.get("aacName")) &&
Accountmap.get("aacNumber").equals(myMap.get("aacNumber")))))
{
finalList.add(Accountmap);
new Map<String,Object> Accountmap = new HashMap<>();
Accountmap.put("aacID",myMap.get("aacID"));
Accountmap.put("aacName",myMap.get("aacName"));
Accountmap.put("aacNumber",myMap.get("aacNumber"));
}
}
finally once you have all your unique accounts in your finalList you can then loop through it and compare their unique Ids to each entry in the comparisonMap so you can put in entries (currencyMaps) into those unique Id maps (accountMaps).
for(HashMap<String,Object> accountMap:finalList){
//put in the key "currency" and the value as a currencyMap.
//the currencyMaps are gotten by matching the Ids from the accountMap to the Id
//in the comparisonMap
//conveniently the ID maps to its currencyMap
accountMap.put("currencies",comparisonMap.get(accountMap.get("aacId")))
}
Notes about output
At the end your finalList would contain the list of accountMaps as the desired output for this question. I don't make any guarantees on the run-ability of this code but It shows a general method to achieving what you need.
this solution assumes your accounts are listed like they are in the question. It won't work as expected if the same account info is repeated AND split between accounts down the list.
(i. e.) nothing like:
Account 1 information
Account 2 information
Account 1 information repeated.
the last entry would cause duplicate entries in your finalList

filter unique list from json

I have two drop downs, one is street and the other is apt. Street and apt are the properties of address class. I have a unique_seq_no for each address, so i store it in a HashMap.
LinkedHashMap<String, Address> addressMap = new LinkedHashMap<String, Address >();
Property prop = new Property();
ArrayList<Property> ap = new ArrayList<Property>();
for(Offices of: offList)
{
Address ad = new Address();
ad.setStreet(of.getAdd());
ad.setApt(of.getUnit());
ad.setUnique_seq_no(of.getSequence());
addressMap.put(of.getSequence(),ad);
prop.setAddSeq(of.getSequence());
prop.setAdd(of.getAdd());
ap.add(prop)
}
This returns a JSON of,
[{seq:23456,add:1234 NW st,apt:201},{seq:45678,add:1234 NW st,apt:202},
{seq:57689,add:6785 NW st,apt:203}]
Issues,
1. In the street drop down it displays duplicate add.
Once the user selects the add from the drop down(for eg: 1234 NW st- the repeated add), it picks the seq in which it stored and displays only that apt.
I want to create a map with street as key, and a list of apts as the value. Since street is duplicated, how do we achieve this.
Here i how you can get to the required solution. I believe you are correct till "addressMap" is populated with key as sequenceNo & value as "Address" Object which holds street, apartment & sequence number.
Next thing you will need to do is iterate through adressMap & populate anotherMap which holds key as street (which should be unique) & value as "List of Apartment". This is how you can take this forward.
ArrayList ap = new ArrayList();
for (Offices of : offlist) {
Address ad = new Address();
ad.setStreet(of.getAddress());
ad.setApt(of.getUnit());
ad.setUnique_seq_no(of.getSequence());
addressMap.put(of.getSequence(), ad);
}
HashMap<String,ArrayList<String>> finalMap = new HashMap<String,ArrayList<String>>();
for (Entry<String, Address> entry : addressMap.entrySet()) {
Address address= entry.getValue();
finalMap.put(address.getStreet(),getList(address.getStreet() , finalMap , address.getApt()));
}
"getList" is the method which takes care of adding list of Apartment to the same street key if already exists.
Now you will need to below code to populate finalMap which consists of unique street as key & list of apartments as value.
private static ArrayList<String> getList(String street,HashMap<String,ArrayList<String>> adressMap , String apt){
if(adressMap != null && adressMap.get(street) != null){
ArrayList<String> list = adressMap.get(street);
list.add(apt);
return list;
}else{
ArrayList<String> list = new ArrayList<String>();
list.add(apt);
return list;
}
}
If you convert the finalMap to JSON string, below will be format of string you will see.
{"678 NW":["101"],"124 NW":["101"],"1234 NW":["102","103"]}

Value of HashMap inside a Hashmap in Java

I have this hashmap of students which stores the id, name and last name.
So I created this :
Map<Interger, HashMap<String,String>> students = new HashMap<>();
where the second hashmap stores the name and lastname.
My goal is to look for a student in a swing application, I succeed in searching with id because it's the key of the first hashmap, but i'd like to use all of them like this:
So my question is : If I want to search by name or last name, how can i get the value of the first hashmap and put it in a new hashmap ?
You can iterate on the hashmap like this :
private int searchByName(String s) {
for(Map.Entry<Integer, HashMap<String, String>> entry : students.entrySet()) {
HashMap student = entry.getValue(); // Hashmap containing first and lastname
if (student.containsKey(s)) // If name match
return entry.getKey(); // Return the student ID
}
return 0; // Student not found
}
For the lastname just use containsValue(s) instead of containsKey(s)
You can use the Google Collections API Guava for that specifically a BiMap
A bimap (or "bidirectional map") is a map that preserves the
uniqueness of its values as well as that of its keys. This constraint
enables bimaps to support an "inverse view", which is another bimap
containing the same entries as this bimap but with reversed keys and
values.
With this you'will be able to search using first name and last name. This BiMap will be value to your first parent hashmap.
I am not sure if the data structure is the best for your use-case but answering to your question, you should try using values() method which would return you the collection of values of the Map
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#values()
Collection res = studensts.values();
Iterator<HashMap<String, String>> i = res.iterator();
Map<String,String> resM = null;
while(i.hasNext()){
resM = i.next();
}

Categories