How to initiate multidimensional arraylist with different objects? - java

I'm having trouble trying to initiate an arraylist in which the first column I want to be a string, and the second column be a custom object.
For example column [0] be String, and column[1] be an Integer. Convention attempts of creating a multidimensional arraylist as in those used by int[][] or String[][] don't seem to work :( I would welcome any help. At this point I don't think it's something java allows. I can make it work for just one type of object but it's not what I want. Thanks!

Do you need an arraylist? You could create a Map<String, Object> or Map<String, Integer> or whatever you need..

Sure it does, but you weaken/eliminate type-checking:
Map myMap<String>, Integer> myData = new HashMap<String, Integer>();
Now your list of strings can be retrieved by myMap.keySet() and values can be retrieved by myMap.values(). Each of these return a Set, which you can easily convert to a List using the following code:
List<String> strings = new ArrayList<String>(myMap.keySet()); // get your strings
List<Integer> numbers = new ArrayList<Integer>(myMap.values(); // get your numbers
Good luck and if you should run into problems, do leave a comment.

Arrays are geared towards one specific type of thing - be they Object or String or int. Despite the fact that you're adding multiple dimensions to them, they still only hold one type of information.
What you would rather have is a mapping between two objects. This allows you to do the following:
Associate any key to a particular value
Eliminate duplicate key entries
Be much easier to access instead of array indexing
Here's an example. Say your custom object is a Cat, and you want to map the name of the owner to a particular Cat. You create a new instance of a Map.
Map<String, Cat> catOwners = new HashMap<>();
You can then put elements into it...
catOwners.put("Jamie", new Cat("Tycho"));
...and retrieve them with relative ease.
Cat currentCat = catOwners.get("Jamie"); // gets Jamie's cat
if you really want to, you can even iterate over them using the Map.Entry object provided with all Maps:
for(Map.Entry<String, Cat> element : catOwners.entrySet()) {
System.out.println(element.getKey()
+ " owns " + element.getValue().getName());
}

What you can do is use the generic Object type, and cast accordingly.

Related

What is a efficient way to condense a List of objects to based on an object value?

I have an ArrayList of Objects. The object has five fields: id, date, name, value, adjusted_value. The list may hold multiple entries with the same name, and I am having trouble devising an efficient way to condense the list based on the name to where I will a list of similar objects but the values stored will be name, sum(value), sum(adjusted_value).
Is there an efficient way to do this? My current method has for loops inside of a do-while.
Clarfication:
I have a list of obejcts :
{id,date,name,value,ajusted_value},
{1,"10/30/2014","peaches",4,3}
{2,"10/30/2014","apples",2,2}
{3,"10/31/2014","peaches",3,1}
.
.
.
I want to condense to list based the name value to one that looks like this:
{null,null,"peaches",7,4}
{null,null,"apples",2,2}
.
.
.
However, I found that HashMap's put() functionality will perform what I desire automatically, but now I need to do this sort of action in Javascript if possible.
You can define a Map where the key is the name and value is the object instance.
Go through the list and for each instance check whether it exists in the map.
If not just add to the map. map.put(instance.name,instance)
If it's already added to the map just
mapInstance=map.get(instance.name);
mapInstance.value+=instance.value;
mapInstance.adjusted_value+=instance.adjusted_value;
After the loop you have the filled map with grouped data
I would use Guava in two step. Use a NameFunction to convert the list to a Multimap. Use a CondenseFunction to convert the values of the Multimap.
Function<MyClass, String> toName = new Function(){
public String apply(MyClass input){return input.name;}};
ImmutableListMultimap<String, MyClass> multimap = Multimaps.index(myList, toName);
Map<String, Collection<MyClass>> map = multimap.asMap();
Function<Collection<MyClass>, MyClass> condense= new Function(){
public MyClass apply(Collection<MyClass>input){
// create sums here
}};
Map<String, MyClass> condensed = Maps.transformValues(map, condense);
Collection<MyClass> result = condensed.getValues();
Multimaps.index()
Maps.transformValues

Java- Adding unique values to Hashmap

ok,
here is my issue....I have a List<short>letterList which has for example: "1,2,3,4,5,6,7,8,9,10"
What Im doing is Im iterating over this list then passing the value into another method which returns a value:
so:
string value = null;
for(Short foo : letterList)
{
value = getSomeValue(foo) //returns a letter A or B or C
}
What Im trying to do is get a hashmap to look something like this:
key: a, value 1,5,7
key b, value: 2,3,4
key c, value: 6,8,9,10
not these values specifically, but you get my point
Im not sure how to do this I have tried creating a map with a <set<string>, List<short>
any suggestions would be appreciated
HashMap<Character, List<Short>> map
My understanding was you were looking for a simple way to store a list of values with a character? If so, use that above.
If you want to sort by letter (for easy printing out) use the following:
TreeMap<Character, List<Short>> map
You can get and of the values by using map.get('A') and using your standard methods to iterate through or get a certain value from the associated list.
Java has no built-in MultiMap, but you can either simulate a multimap (Map<String, List<Short>>) or try out Guava for example: https://code.google.com/p/guava-libraries/
Map<String, List<Short>>
The key (String) will be unique. The List<> will be able to hold a list of shorts.
If you want to make sure the numbers are unique as well as the keys, then use a Set instead of a list.
Remember to initialize the lists you put in the map (getting a key like "A" for the first time will return null, so check if it's null and if it is then create a List, put your value into it, and put the list into the map).
Not knowing your complete use case, I would suggest having a different look at your data structure organization. e.g.
Map<Integer, String> map = new HashMap<Integer, String>();
Where the keys are 1,2....10 as in your example and the values are
1 -> a
2 -> b
3 -> b
etc.
To get your original "list" you can use -
Set<Integer> numbers = map.keySet();

Cannot Create an LinkedList<String, int>

i want to create an LinkedList of couple that the key is a String and the value is an integer ?
LinkedList doesn't have a key. It's a list of elements, not a key/value mapping.
If you want a LinkedList where each element is a pair of Integer/String values, you'll need to pick one of:
Create a generic Pair class
(Ab)use an existing generic class (e.g. Map.Entry)
Create a custom class for your specific scenario
I would suggest the last option as the most sensible one - you'll be able to give it appropriate semantics and names according to the real meaning of the string and the integer. Heck, you'll also be able to avoid boxing the integer, as you can have:
public class WhateverYouCallIt {
private final int firstValue;
private final String secondValue;
// Constructor, properties
}
You can only use Object in a LinkedList., this means you cant use Java Primitives.
However, what you seem to need is a Map structure.
I recommend using java.util.HashMap, it allows you to create a Key, Value pairs.
Example:
HashMap<String,Integer> a = new HashMap<String,Integer>();
a.put("one",1);
a.put("two",2);
System.out.println(a.get("one"));
//prints 1
System.out.println(a.get("two"));
//prints 2
EDIT:
As per your comment, i see you required order, use the following example then:
LinkedHashMap<String, Integer> b = new LinkedHashMap<String,Integer>();
b.put("one",1);
b.put("two",2);
b.put("a",3);
for (String key:b.keySet())
{
System.out.println(b.get(key)); // print 1 then 2 finally 3
}
Hope this is what you were asking (if so, modify your question).
One error is you need Integer instead of int, but as others have pointed out LinkedList doesn't take Key/Value pairs.
I'd imagine a HashMap is what your after. As other have stated, you cannot use a primitive type such as "int" in a library storage class like LinkedList, or ArrayList, you must instead use an object such as "Integer".
HashMap hash = new HashMap();
Read this for more information: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html

Nested Hashmap updates all the values for all the keys instead the one I want to change

I have a hashmap that contains 10 children hashmap, each of these child hashmap 5 keys mapping to a String array. When I want to update a value for a specific key from a children hashmap, all the keys get updated instead; not only that, but also all the children hashmap get updated as well. This code illustrate what I'm doing.
HashMap<String, HashMap<String, String[]>> parentMap = new HashMap<String, HashMap<String, String[]>>();
for(String x : someArray){ // Adds 10 children hashmaps to parentMap
parentMap.put(x,new HashMap<String, String[]>());
for(String y : someOtherArray){ // Creates 5 keys for each of the children hashmaps
parentMap.get(x).put(y,stringArray);
}
}
parentMap.get(someKey).put(someOtherKey,modifiedArray); // This updates the entry I want to update.
When I update with that last instruction, I want to update specifically that key, however everything gets updated instead, all the keys for all the children hashmaps are updated instead the one I want.
Hopefully it makes sense, I'm not sure if this is the correct approach for this but I've been looking online for any tips on doing something similar without any luck. I'm not good at all with Java, if I can achieve the same result with something simpler, it will be welcome, note that I can't use a List or something like that, since it uses int indexes, I need to reference to my objects using a string (like a dictionary on python).
That is because you initialize all maps to contain stringArray, i.e., the same array.
This is why changing one of them, will change all of them.
If you want each key in each inner map to point to different copies of the array, you need to do something like
...
parentMap.get(x).put(y, Arrays.copyOf(stringArray, stringArray.length));
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
...
(You could also use for instance clone or create new arrays manually each time you need a new copy.)
#aioobe explained the reason.
Here is the solution. You have to create copy of initial array every time you put it into your map:
String[] tmpArr = new String[stringArray.length];
arraycopy(stringArr, 0, tmpArr, 0, stringArray.length);
parentMap.get(x).put(y,stringArray);

Java: Using a hashmap, retrieving all values and calling methods

I have a need to store a list of dynamically created objects in a way where they can all be retrieved and their methods called on demand.
As far as I can see for the list and creation, a HashMap fits my needs but i'm a bit puzzled on recalling the objects and calling their methods using the HashMap.
Just as a reference, let me give you a little code:
Here is the HashMap:
Map<String, Object> unitMap = new HashMap<String, Object>();
// here is how I put an object in the Map notice i'm passing coordinates to the constructor:
unitMap.put("1", new Worker(240, 240));
unitMap.put("2", new Worker(240, 240));
Now I need to create a method that retrieves every object in the hashmap and call a method from each object. is this possible or can the created objects only be referenced directly. If so, is there another way to call a method of all existing instances of a class dynamically (in other words, on user input)?
Sure. You can do this:
for (Object thing : unitMap.values()) {
// use "thing" here
}
If you need the keys too, you can either get just the keys:
for (String key : unitMap.keySet()) {
// use "key" here
}
or both the keys and values together:
for (Map.Entry<String, Object> entry : unitMap.entrySet()) {
// use "entry.getKey()" and "entry.getValue()"
}
In all the above cases, each entry in the map is traversed one by one. So at the end of the loop, you'll have processed all the entries in the map.
If all of the values in the Map are Worker objects, you should declare your map to be of type Map<String, Worker>. This way, when you pull a value out of the map, it will be typed as a Worker. This way you can call any method declared on Worker as opposed to having to check the type at runtime using instanceof.
If the map holds different values, and you need to keep the value type as Object, it may be advantageous to use an interface to define the method that you want to call for each different object type.
If you do not know what method you want to run on the values until runtime, and the map can hold different values, you will just have to do what you are currently doing, and use Map<String, Object>.
Finally, to get the values of the map, you do just as Chris Jester-Young mentioned before me. The biggest advantage, as I said previously, is that your objects will be typed, and you will have no need for casting/instanceof checking.
I use this to put all values from hashMap on a List, hope it helps.
private List<String> getValuesFromHashMap(HashMap<String, String> hashMap) {
List<String> values = new ArrayList<String>();
for (String item : hashMap.values()) {
values.add(item);
}
return values;
}

Categories

Resources