I am very new in java. I want to create a kind of complex array. I think its called list/collection/map...
My data looks like
-item
ref:GH987
size:22
date:1992
-item
ref:98KJ
size:27
date:2000
-item
ref:ZXJ212
size:24
date:1999
I do not prefer to create an item Class and store the 3 instance in an array.
I found something called Map but it really confused me and I don't understand how could I access the values after creating the data. Could you help me how to start with this ?
final Map<String, List<String>> data = new LinkedHashMap<String, List<String>>();
data.put("item", new LinkedList<String>());
You have to create an Item class, that's the whole point of OOP!
Very minimal example:
public class Item {
public String ref;
public int size;
public int date;
public Item(String ref, int size, int date) {
this.ref = ref;
this.size = size;
this.date = date;
}
}
Then it's just a List<Item> and you can access each part with myList.get(i).ref etc:
List<Item> l = new ArrayList<>();
l.add(new Item("GH987", 22, 1992));
l.add(new Item("98KJ", 27, 2000));
...
for (Item it : l)
System.out.println("Ref: "+item.ref+", size: "+item.size+", date: "+item.date);
Now, if you really want to use a Map to store each attribute, you have to think what would be your unique key. Let's suppose it's ref, which is a String:
Map<String,Integer> sizes = new LinkedHashMap<>(); // LinkedHashMap keeps the insert order
Map<String,Integer> dates = new LinkedHashMap<>();
sizes.put("GH987", 22);
dates.put("GH987", 1992);
sizes.put("98KJ", 27);
dates.put("98KJ", 2000);
then it's difficult to access all members as they're not bundled in a single instance:
String ref = "GH987";
System.out.println("Ref: "+ref+", size: "+sizes.get(ref)+", date: "+dates.get(ref))
Here you should realize that if a Map hasn't been updated, it will return null on the value and you'll have to handle consistency yourself. It is also a pain to create so many objects just to store single attributes, which in your case are Number subclasses (e.g. Integer) instead of native types, which are far more efficient.
So do yourself a favor, and create your Item class. Then you can use a Map to quickly access a particular item based on its key, which looks like the ref member:
myMap.put(ref, new Item(ref, size, date));
Item it = myMap.get(ref);
...
Yes you can choose Map with a class and having it's reference as a key for ex
Map<String,Item> map = new HashMap<>();
Assuming reference is unique. You can store values like
map.put(item.getReference(),item);
Related
I'm looking to sort a TreeMap of Customer objects by a specific Customer property.
The TreeMap is defined as so:
private TreeMap<Long,Customer> customerMap = new TreeMap<>();
Long is the type of ID for the customers stored.
I wrote a function to create a new TreeMap and pass a Comparator to its constructor which gets map entries, their values, that compares the specific field.
public Customer[] getCustomersByName() {
TreeMap<Long,Customer> sortByName = new TreeMap<> (
new Comparator<Map.Entry<Long,Customer>>() {
#Override public int compare(Map.Entry<Long,Customer> cus1, Map.Entry<Long,Customer> cus2) {
return cus1.getValue().getLastName().compareTo(cus2.getValue().getLastName());
}
}
);
sortByName.putAll(customerMap);
// sortByName to Customer[] and return.
}
This doesn't work and throws: Cannot infer type arguments for TreeMap<>Java(16778094) at Line 2.
Perhaps, the issue is that the Comparator takes <Map.Entry<K,V>> to compare a TreeMap<K,V> and that is the issue.
How would I fix this though to sort by values but keep the customerMap type as is?
I know that TreeMaps are only sorted by keys. Is there a better data structure for this job perhaps so that I could store a bunch of Customer objects and sort them by different Customer properties without the operation being too expensive (not polynomial preferably)?
Set up a second TreeMap, using the customers last name as the key:
TreeMap<String,Customer> sortByName = new TreeMap<>();
TreeMap<Long,Customer> sortByID = new TreeMap<>();
----------------
sortByName.put(customer.getLastName(), customer);
sortByID.put(new Long(customer.getID()), customer);
----------------
return sortByName.values().toArray( new Customer[sortByName.size()] );
'''
This is rather easy with streams:
Customer[] cust =
customerMap.values()
.stream()
.sorted(Comparator.comparing(Customer::getName))
.toArray(Customer[]::new);
You only need to sort the values according to your example, so why bother sorting the TreeMap in reverse, when the only thing you care about is a sorted (by name) Customer[]?
I have:
public static HashMap<String, String> CHILD_NAME_DOB = new HashMap<>();
Suppose the values in CHILD_NAME_DOB are:
<adam,15121990>
<roy,01051995>
<neha,05091992>
<alisha,11051992>
I am trying to fetch the last key element from CHILD_NAME_DOB. That is, I want to fetch key alisha from the example above to temporary String name.
Also I want to know on how to fetch data by index.
Eg.: if int index = 2 , I want key "Neha" in String name
TIA.
Edit: DateOfBirth value (value data in CHILD_NAME_DOB) is dynamic and is unknown. So THIS LINK is not what I want.
Single line solution:
First note that the Java HashMap does not guarantee the order of entries. So each time you iterate over a HashMap, entries appear in different positions. You will need LinkedHashMap that guarantees the predictable iteration order.
Map<String, String> CHILD_NAME_DOB = new LinkedHashMap<>();
Get the key by index:
key = (new ArrayList<>(CHILD_NAME_DOB.keySet())).get(index)
Get the value by index:
CHILD_NAME_DOB.get(key)
Thanks to #Pentium10 for this answer.
And I little modified it according to my need.
String key="default";
Iterator myVeryOwnIterator = CHILD_NAME_DOB.keySet().iterator();
while(myVeryOwnIterator.hasNext()) {
key=(String)myVeryOwnIterator.next();
//String value=(String)meMap.get(key);
}
Toast.makeText(viewEnterChildExp.getContext(), "Key: "+key , Toast.LENGTH_LONG).show();
I'm getting the last key element by this.
I'll update as soon I also get to find an easy way to key by index.
This way to get key....
public static String getHashMapKeyFromIndex(HashMap hashMap, int index){
String key = null;
HashMap <String,Object> hs = hashMap;
int pos=0;
for(Map.Entry<String, Object> entry : hs.entrySet())
{
if(index==pos){
key=entry.getKey();
}
pos++;
}
return key;
}
You can also use an ArrayMap instead of a HashMap. To get the value by index use:
ArrayMap.valueAt(index);
To get the Key at an index use:
ArrayMap.keyAt(index);
Fetching the "last" key and fetch by index is not supported by HashMap. You can use a LinkedHashMap and lookup the element with index 2 (or the last element) by iterating over it. But this will be a O(n) operation.
I suggest you use a List<Pair<String, String>> if the order of the keys/values is important to you and you wish to do index based lookup.
If both key based and index based lookup is important to you, you could use a combined data structure that consists of both a List and a HashMap, but note that removal of elements will be O(n).
You can create a class Child
public class Child(){
private String name;
private String number;
....
}
and then put this object in a List
public static List<Child> CHILD_NAME_DOB = new ArrayList<Child>(); // using LinkedList would defeat the purpose
in this way you can invoke the method get(int index), that returns the element at the specified position in this list.
In your example
<adam,15121990>
<roy,01051995>
<neha,05091992>
<alisha,11051992>
invoking CHILD_NAME_DOB.get(2) you'll get <neha,05091992>(as Child object)
HashMap does not have a concept of ordering, so getting the n-th entry does not make sense. You could use a TreeMap instead, which is ordered on its keys.
However, you should reconsider your model as you seem to have conflicting interests. On the one hand, accessing by index is typical for Lists, whereas accessing by key is typical for Maps. I'm not sure in which situation you'd want to do both.
If you really want to do both index and key accessing, you could write your own data structure that stores the data in a list combined with a mapping from key to index and vice versa. I would recommend against this, but if that's really what you want, then I think that's the best solution.
I know it is not the best solution, but what about this solution (pseudocode!). Just combine List and Map in one class.
public class UserBirthday {
private List<String> names = new ArrayList<>();
private Map<String, String> CHILD_NAME_DOB = new HashMap<String, String>();
public void add(String name, String bd) {
if (!CHILD_NAME_DOB.containsKey(name)) {
names.add(name);
}
CHILD_NAME_DOB.put(name, bd);
}
public String getByName(String name) {
return CHILD_NAME_DOB.get(name);
}
public String getByIndex(int index) {
return getByName(names.get(index)); // TODO: range test
}
public static void main(String[] args) {
UserBirthday ub = new UserBirthday();
ub.add("dit", "12345678");
ub.add("lea", "234239423");
ub.add("alex", "43534534");
ub.add("ted", "099098790");
System.out.println(ub.getByIndex(2));
System.out.println(ub.getByName("alex"));
}
}
You may get some problems if you remove an entry, but it should be just a suggestion.
for (String key : hmList.keySet()) {
String value = hmList.get(key);
Log.e("HashMap values", "key=" + key + " ,value=" + value);
}
I need to store different types of DATA inside one same "array" associated to a key (or an ID) in my android application, and I'm wondering if there's a way to create HashMaps (or equivalent dynamic arrays) that have more than one column of content. Like this for example.
HashMap<Integer, String, LatLng, Marker> myHashMap = new HashMap<Integer, String, LatLng, Marker>();
Thanks in advance for any idea.
private class Row {
public Integer i;
public String s;
public LatLng ll;
public Row(Integer i, String s, LatLng ll) {
this.i = i;
this.s = s;
this.ll = ll;
}
}
List<Row> rows = new ArrayList<Row>();
This is semi pseudo code but I think you get the idea
Adding new Rows to the list can be done with
rows.add(new Row(new Integer(1), "a string", new LatLng(51.448495, 5.470877));
Editing a row can be done with
rowIndex = 3;
Row row = rows.get(rowIndex);
row.i = 2; //give a new value
//etc
Edit: replaced pseude code with real code
map is just a key and value so HashMap makes very little sense
Java does not let you define data structured this way. A collection of type Class A should have hold only instance of Class A or its sub type.
EDIT: From the data you have provided seems like you want to process each row from a database table. Most appropriate data structure for it is to have a class with fields that correspond to a database table.
When you fetch a row from the a result set just create an instance of this class.
Class mysqlTuple
{
public Integer id;
public String message;
public LatLng latitude;
public Marker longitude;
}
mysqlTupe [] mysqlTable = new mysqlTupe [];
It depends a lot on what you are trying to achieve
One option is to keep 3 different maps:
Map<String, Integer>
Map<String,Marker>
Map<String,LatLng>
Another option is to make a:
Map<String,Object>
However you will have to 'instanceof' to check the real type, which is not a best practice.
I know that HashMap doesn’t allow duplicate keys (It does allow duplicate values).
However in this example that works perfectly,all the values have the same key(that means the key is not unique)Maybe I misunderstood the code.Could someone help me understand it right.
this is the code
public class PlayListManager {
//**********************************hashmap keys************************
public static final String ALL_VIDEOS = "AllVideos";
public static final String ALL_Songs = "AllSongs";
//***************************************************************************
..
...
....
while (cursor.moveToNext()) {
Songs song = new Songs();
song.songId = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
song.artist = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
song.title = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
song.songName = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
song.duration = Integer.parseInt(cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)));
song.albumId = Integer.parseInt(cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)));
song.songData = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
//*******here it uses the same ky for all the videos?!!*************
HashMap<String, Object> songMap = new HashMap<String, Object>();
songMap.put(ALL_Songs, song);
songsList.add(songMap);
}
}
In each iteration of the while loop, the code is creating a new HashMap instance and filling it with only one entry that maps a String key ("AllSongs") to the Song object.
This map (which contains only one entry) will then be added to the list songsList.
After the while loop is finished, you would have a list of HashMaps where each map basically maps a hardcoded keyword to one song.
songsList:
<"AllSongs", song1>, <"AllSongs", song2>, <"AllSongs", song3>, ...
In this case, using a HashMap seems redundant. You could just fill the list with the Song instances without saving each one in a map.
The key concept here is that there are many HashMap (each iteration creates one), as opposed to having a "global" HashMap. If it were global, each song would overwrite the other since they are always mapped using the same hardcoded key.
I have a hashmap for orders and another one for orderitems. A method which puts the data into the hashmaps is executed like this:
// THIS ONE ADDS THE ORDERS
// (int orderNumber, String Datum, String salesperson, int customernumber)
mainController.addBestallning(500, "2012/01/01", "Hendrik Gustafsson", 1001);
// THIS ONE ADDS THE ORDERED ITEMS
// (int orderNumber, int linePos, Artikel product, int amount, double price)
mainController.addBestallningsOrderRad(500, 1, mainController.getAllaArtiklar().get(101), 5, 100.00);
Once I find an order by its ordernumber, how do I find the ordereditems?
The only link I have now is the ordernumber, which I save in orderitemshashmap, so I assume some sort of iteration needs to take place, find the matches and return the results.
I tried doing this and got it to work, but only under condition that all of the orderitem positions are also unique.
So, if I was to add another order like this:
mainController.addBestallning(501, "2011/05/02", "Sven Karmageddon", 1002);
mainController.addBestallningsOrderRad(501, 1, mainController.getAllaArtiklar().get(101), 5, 100.00);
I could not find the orderitems for order 501.
Here is what I tried so far. Made a method to find all orders of a customer:
public HashMap<Integer, Bestallning> getAllaKundOrdrar() {
HashMap<Integer, Bestallning> allaKundOrderHashMap = new HashMap<>();
//iterate through all orders
//find the ones which belong to customerid
//place them in allaKundOrderHashMap
//return allaKundOrderHashMap
Iterator iter = tmpBestallningsregister.getAllaBestallningar().keySet().iterator();
while (iter.hasNext()) {
Integer key = (Integer) iter.next();
//String value = (String) controller.getAllaKunder().get(key).getKundNamn();
if ((customerNrToFindOrdersFor) == getAllaBestallningar().get(key).getKundNr()) {
//found an order for this customer, putting it in the hashmap
allaKundOrderHashMap.put(key, getAllaBestallningar().get(key));
}
}
return allaKundOrderHashMap;
}
A method to find all ordereditems from all customers (100% wrong to search like this, I know) and get the ones beloning to a specific order:
//RETURN OF ORDERRADERS HASHMAP FOR SPECIFIC ORDER VIA ORDERREGISTER
public HashMap<Integer, BestallningsOrderRad> getAllaBestallningsBestallningsOrderRader() {
HashMap<Integer, BestallningsOrderRad> allaBestallningsOrderRaderHashMap = new HashMap<>();
//iterate through all orderrader
//find the ones which belong to orderid
//place them in allaKundOrderRaderHashMap
//return allaKundOrderRaderHashMap
Iterator iter = tmpBestallningsregister.getAllaBestallningsOrderRader().keySet().iterator();
while (iter.hasNext()) {
Integer key = (Integer) iter.next();
if ((orderNrToFindOrderRaderFor) == tmpBestallningsregister.getAllaBestallningsOrderRader().get(key).getBestallningsNr()) {
//found an orderrad for this order, putting it in the hashmap
//allaBestallningsOrderRaderHashMap.put(key, getAllaBestallningsOrderRader().get(key));
allaBestallningsOrderRaderHashMap.put(key, getAllaBestallningsOrderRader().get(key));
}
}
return allaBestallningsOrderRaderHashMap;
}
Anyone care to tell me what is it that I am doing wrong?
I've been at this for 20 hours straight...
Don't use two different Map, but only one. What you need is to properly define a Order class that holds all the order data (including suborders, which are sheldom used outside the order) and use just a Map<Integer,Order>
If you insist in having two separate Maps, the second uses the same id but stores a List (it looks like you want it ordered) of suborders.
private Map<Integer, Order> orders;
private Map<Integer, List<SubOrder> suborders;
Stopping a moment before beginning to code and thinking the more appropiate data structures will usually save you a lot of "hell" later.