Retrieving object by ID using map - java

Hi i Was looking for method to retrieve ArrayList object by object's ID, some guy in topic from 2013 told that you should use Map to do this. But how can i use Object ID as a Map key?
Map<Item.getId(),Item> items = new TreeMap<>();

class Item {
// id could be any type you like. Mostly this is simple types: int, long, String, UUID
private final int id;
// ... other fields
}
Map<Integer, Item> map = new HashMap<>();
map.put(666, new Item(666));
Item item = map.get(666); // get an item with id=666;
P.S. Additionally, make sure that you realize how hashCode() and equals() work.

Related

Best approach to have multiple key-value pairs, in a Value of an outer key

I am trying to create a dictionary type record, that holds for example key="Book name" and value= (key="price": $250, key="qty": 10). What would be the easiest way to achieve this is Java ? I have tried by creating a separate class object for they Value.
public class book_info {
int price = 0;
int qty = 0;
public void book_info(int qty, int price){
this.qty = qty;
this.price = price;
}
}
and creating a HashMap instance;
Map <String, book_info> items = new HashMap<String, book_info>();
items.put("Book1", new book_info(600, 20));
items.put("Book2", new book_info(200, 30));
items.put("Book3", new book_info(100, 50));
This works fine but is there any other alternate way by NOT using a separate class object, instead by just adding multiple key-value pairs in the initialization of HashMap like this;
Map <String, <<String, Integer>,<String, Integer>>> items = new HashMap<String, <<String, Integer>,<String, Integer>>>();
your question was probably already been answered, what your trying to do is use an object as the maping key, so instead of having [key, object] you want to have [object1, object2] and each object can be a map of which at the end will make them [[key1, value1][key2, value2]] for more details on using objects as keys see answer:
Using an instance of an object as a key in hashmap, and then access it with exactly new object?

Java - How do I add a new value to an existing key in a Hash Map. 1 key, multiple values

I am trying to create a method that, when given a key and a value, can access the map via the key and then either add or replace that specific value.
My Hash Map is created like so:
public Band(){
musicians = new HashMap<>();
}
And I can add new entries like so, with band acting as the key:
public void addMapEntry(String band, String name, String instrument, int experience){
musicians.put(band, new Musician(name, instrument, experience));
}
My new method header look like this:
public void addValue(){ }
I have tried using the put method but I can't get it work as I'd like.
I have also tried iterating through the map, but I've only ever used that method to return map objects in a list, whereas I don't want to return anything in this method. I want to be able to send it two arguments (the key and the value) and have it only replace that specific value.
I hope I have been clear in my explanation.
Java Map is single value for each key.
If you need multiple values for a single key, you should make the type a collection of the appropriate type and add your own logic for adding a new value. Your Band class should have methods to add/remove a Musician and handle the details in the private implementation.
public class Band {
private Map<String, List<Musician>> members = new HashMap<String, List<Musician>>();
public void addMusician(String key, Musician musician) {
if (this.members.containsKey(key) {
List<Musician> musicians = this.members.get(key);
if (musician != null) {
musicians.add(musician);
this.members.put(key, musicians);
}
}
}
public void removeMusician(String key, Musician musician) {
// should be clear enough from the add method.
}
}
I think the most suitable for you is to use Guava Multimap
ListMultimap<String, String> musicianMap = ArrayListMultimap.create();
Then add as many musicians to your band
musicianMap.put("Beatles", new Musician("Jhon Lennon"));
musicianMap.put("Beatles", new Musician("Paul McCartney"));
musicianMap.put("Beatles", new Musician("Ringo Starr"));
musicianMap.put("Beatles", new Musician("George Harrison"));
And you can pull them all using just key.
musicianMap.get("Beatles")
This will return a list of ["John Lenon", "Paul McCartney", "Ringo Starr"] of course these will objects of class Musician.

Group objects in list by multiple fields

I have a simple object like this
public class Person {
private int id;
private int age;
private String hobby;
//getters, setters
}
I want to group a list of Person by attributes
Output should be like this
Person count/Age/Hobby
2/18/Basket
5/20/football
With a chart for more understanding
X axis : hobby repartition
Y axis : count of person distribution
Colors represents age
I managed to group by one attribute using map, but I can't figure how to group by multiples attributes
//group only by age . I want to group by hobby too
personMapGroupped = new LinkedHashMap<String, List<Person>>();
for (Person person : listPerson) {
String key = person.getAge();
if (personMapGroupped.get(key) == null) {
personMapGroupped.put(key, new ArrayList<Person>());
}
personMapGroupped.get(key).add(person);
}
Then I retrieve the groupable object like this
for (Map.Entry<String, List<Person>> entry : personMapGroupped .entrySet()) {
String key = entry.getKey();// group by age
String value = entry.getValue(); // person count
// I want to retrieve the group by hobby here too...
}
Any advice would be appreciated.
Thank you very much
Implement methods for comparing people according to the different fields. For instance, if you want to group by age, add this method to Person:
public static Comparator<Person> getAgeComparator(){
return new Comparator<Person>() {
#Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
};
}
Then you can simply call: Arrays.sort(people,Person.getAgeComparator()) or use the following code to sort a Collection:
List<Person> people = new ArrayList<>();
people.sort(Person.getAgeComparator());
To sort using more than one Comparator simultaneously, you first define a Comparator for each field (e.g. one for age and one for names). Then you can combine them using a ComparatorChain. You would use the ComparatorChain as follows:
ComparatorChain chain = new ComparatorChain();
chain.addComparator(Person.getNameComparator());
chain.addComparator(Person.getAgeComparator());
You could simply combine the attributes to a key.
for (Person person : listPerson) {
String key = person.getAge() + ";" + person.getHobby();
if (!personMapGrouped.contains(key)) {
personMapGrouped.put(key, new ArrayList<Person>());
}
personMapGrouped.get(key).add(person);
}
The count of entries is easy to determine by using personMapGrouped.get("18;Football").getSize().
I'm not sure about your requirements, but I'd probably use multiple maps (Google Guava's Multimap would make that easier btw) and sets, e.g. something like this:
//I'm using a HashMultimap since order of persons doesn't seem to be relevant and I want to prevent duplicates
Multimap<Integer, Person> personsByAge = HashMultimap.create();
//I'm using the hobby name here for simplicity, it's probably better to use some enum or Hobby object
Multimap<String, Person> personsByHobby = HashMultimap.create();
//fill the maps here by looping over the persons and adding them (no need to create the value sets manually
Since I use value sets Person needs a reasonable implementation of equals() and hashCode() which might make use of the id field. This also will help in querying.
Building subsets would be quite easy:
Set<Person> age18 = personsByAge.get(18);
Set<Person> basketballers = personsByHobby.get( "basketball" );
//making use of Guava again
Set<Person> basketballersAged18 = Sets.intersection( age18, basketballers );
Note that I made use of Google Guava here but you can achieve the same with some additional manual code (e.g. using Map<String, Set<Person>> and manually creating the value sets as well as using the Set.retainAll() method).

How to store multiple objects from a hashmap that has the same key?

EDIT
I've tried this HashMap with multiple values under the same key, and my hashMap now looks like this HashMap<String, List<Place>> placeMap = new HashMap<>();
Also tried to put Object instead of Place(place is my superclass). But when I now create my subclasses and wants to add them to the HashMap I get:
The method put(String, List) in the type HashMap<String,List<Place>> is not applicable for the arguments (String, NamedPlace)
and
The method put(String, List) in the type HashMap<String,List<Place>> is not applicable for the arguments (String, DescPlace)
here is my adding which created the error:
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
placeMap.put(answer, p);
DescPlace dp = new DescPlace(x,y,answer, desc, col, cat);
mp.add(dp);
placeMap.put(answer, dp);
NamedPlace and DescPlace are both subclasses to Place, and I want them both in the same HashMap..
OP
I'm working on a little project here. The thing is that I need to use a HashMap instead of a ArrayList on this part of the project because HashMap is alot faster for searching. I've created a HashMap like this:
HashMap<String, Object> placeMap = new HashMap<>();
The String is the name of the Object, but the thing is that more than one object can have the same name. So I search for a object in my searchfield and I want to store all those objects that has that name into an ArrayList so I can change info in just them.
The object have alot of different values, like name, position, some booleans etc.
Do I need to create a HashCode method into my object class which shall create a unique hashcode?
When using a standard Map<String, List<YourClassHere>> instance, it is important to remember that the map's values for each entry will be a List<YourClassHere>, and will not handle it in any special way. So in your case, if you have
private Map<String, List<Place>> placeMap = new HashMap<>();
Then to store values you will need to do as follows:
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
List<Place> list = placeMap.get (answer);
list.add(p);
However, this piece of code has some underlying problems.
It doesn't take into account that answer might not be present in placeMap.
It assumes that there's always a List<Place> instance for each key you query.
So the best way to fix those potential problems is to do as follows (Java 7 and later):
NamedPlace p = new NamedPlace(x,y,answer,col,cat);
if (placeMap.containsKey (answer) && placeMap.get (answer) != null) {
placeMap.get (answer).add(p);
} else {
List<Place> list = new ArrayList<Place> (); // ..or whatever List implementation you need
list.add (p);
placeMap.put (answer, list);
}
If you want to scna through the list of places, the code would look like this:
if (placeMap.containsKey (key) && placeMap.get (answer) != null) {
for (Place p: placeMap.get (key)) {
// Do stuff
}
}

Any collection object to hold list of combination of more than 2 elements?

Is there a collection object or a approach to hold a combination of elements?
For instance, I need to create a list that contains the combination of the elements name, age, height and weight.
Creating an object for this is not a good idea in my case. Because the number of fields keep changing.
I need to create this list to pass to a query.
Any solution?
class MyContainer {
String someString;
int someInt;
}
List <MyContainer> myList = new List<>();
Something like that!?
I donĀ“t know exactly, what you mean by "Creating an object for this is not a good idea in my case". You could as an alternative create a List<Object> and put in whatever you have or even a List<List<Object>> if you want to have a List of a number of grouped objects.
The best approach would be to make an Object with all the possible elements in it.
class myObject {
String name;
Integer age;
Float weight;
// Etc
}
Or have a base class then have another class which extends this with additional elements
class myExtendedObject extends myObject{
String streetAddress;
String city;
// etc;
}
Then if you don't have an element set it to null... you could always build your query from the object itself by including a method to return your query, juct check if its null and not include in your query (Assuming you mean an sql style query)
public String buildQuery{
String query = "Select * from blahtable Where ";
query += (name != null)?" name = " + name : "";
// etc, or what ever your query needs to be
return query
}
Other wise you could just have a method which returns a map of your elements then you know what the type of each element is based on the key
public Map<String, Object> getElements{
Map<String, Object> myMap = new HashMap<String, Object>();
if(name != null)
myMap.put("Name", name);
// etc
return myMap
}
What about just using a Map for that and use attribute name as key (e.g. Weight )?
You can use any combination of attributes you want and it would be convenient to pass such collection to the query
Consider Enum map should you require more column names type safety

Categories

Resources