I have a small question about converting 2d arraylist to hashmap in java. I have a dataset looks like this after reading as 2d arraylist:
0 1
0 2
1 2
1 3
Which first column stands for id and second column stands for the item. I would like to create frequent itemset using hashmap in java, the output should look like
1 0
2 0 1
3 1
I use these codes but I have some trouble on them:
HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
for(Integer elem : data){
map.put(elem[1], elem[0]);
}
Where data is my 2d arraylist.
The error message said that
incompatible types: ArrayList<Integer> cannot be converted to Integer
for(Integer elem : data){
^
Any help will be appreciated!
You go like this:
List<List<Integer>> inputData = ...
Map<Integer, List<Integer>> dataAsMap = new HashMap<>();
for(List<Integer> row : data){
Integer id = row.get(0);
Integer item = row.get(1);
List<Integer> rowInMap = dataAsMap.get(item);
if (rowInMap == null) {
rowInMap = new ArrayList<>();
dataAsMap.put(item, rowInMap);
}
rowInMap.add(id);
}
Some notes:
You should only be using the interface types List, Map ... as types (you only specify the specific impl type such as HashMap when creating new objects!)
Your problem is: when using for-each on List of Lists (as you did) ... you don't get the individual "cells" Instead, you get Lists [ iterating lists of lists ... results in one list per iteration!]
So, what is left then is to fetch the elements of that inner List, and push them into the Map. The one other part to pay attention to: you want to create a Map of List objects. And those List objects need to be created as well!
( I didn't run the above through a compiler, so beware of typos, but in general it should be telling you what you need to know. If you don't get what the code is doing, I suggest adding println statements or running it in a debugger)
Here is one easy way of doing it:
Take Map<Integer, List<Integer>>
Iterate your Arraylist.
See if key is already present in the map. Retrieve the list and add the value to the list if key is present or else create a new list with the value.
Program:
class FooBar {
public static void main (String[] args) throws Exception {
int[][] data = {{0,1}, {0,2}, {1,2}, {1,3}};
Map<Integer, List<Integer>> myMap = new HashMap<>();
for(int i = 0; i < 4; i++) {
List<Integer> values = myMap.containsKey(data[i][0]) ?
myMap.get(data[i][0]) : new ArrayList<>();
values.add(data[i][1]);
myMap.put(data[i][0], values);
}
System.out.println(myMap);
}
}
Output:
{0=[1, 2], 1=[2, 3]}
This is just to illustrate the basic method. You can obviously modify it to suit your needs. For example, you can have String instead of List<Integer> and choose to append the values to the String instead of adding it to the List.
EDIT:
Here is a sample program with List<List<Integer>> as input. Here I'm assuming the name of this list as input.
Program:
class FooBar {
public static void main (String[] args) throws Exception {
/* Input Data */
List<List<Integer>> input = new ArrayList<>();
input.add(new ArrayList<Integer>(){{add(0); add(1);}});
input.add(new ArrayList<Integer>(){{add(0); add(2);}});
input.add(new ArrayList<Integer>(){{add(1); add(2);}});
input.add(new ArrayList<Integer>(){{add(1); add(3);}});
Map<Integer, List<Integer>> myMap = new HashMap<>();
for(int i = 0; i < input.size(); i++) {
List<Integer> values = myMap.containsKey(input.get(i).get(0)) ?
myMap.get(input.get(i).get(0)) : new ArrayList<>();
values.add(input.get(i).get(1));
myMap.put(input.get(i).get(0), values);
}
System.out.println(myMap);
}
}
Output:
{0=[1, 2], 1=[2, 3]}
Related
I have a global variable masterList, which is a HashMap.
private static HashMap<ArrayList<String>, Integer> masterList =
new HashMap<ArrayList<String>, Integer>();
I have a recursive function, generateAnagram that puts ArrayLists of anagrams in this HashMap with the number of words in the list as the value. However, the HashMap starts to mess up after the first call,and previous ArrayLists are overriden with the new one I'm trying to add, but the previous value remains. This results in two keys with the same value.
Here's a screenshot of the results - Click [here] http://tinypic.com/r/ka1gli/8
private static void generateAnagram(Set<String> subsets, ArrayList<String> currList, letterMap wordMap) {
if (wordMap.count() == 0) {
System.out.println("Adding: " + currList);
masterList.put(currList, currList.size());
System.out.println("Current Master: " + masterList.toString());
} else {
for (String word : subsets) {
if (word.length() <= wordMap.count() && wordMap.isConstructionPossible(word)) {
//System.out.println("Word: " + word + " " + wordMap.isConstructionPossible(word));
wordMap.remove(word);
currList.add(word);
generateAnagram(subsets, currList, wordMap);
currList.remove(word);
wordMap.addBack(word);
}
}
}
}
It's not a good idea to use an ArrayList as the key of a HashMap. Each time you change the content of the ArrayList (by adding or removing elements), its hashCode would change, so even if it's already in the HashMap, get() and containsKey() won't find it, and put() will add it again.
You only have one instance of the ArrayList, which you keep putting in the masterList map, so you would have only one entry in your map if you didn't change the contents of that list all the time.
You need to look at this from the point of view of the parameters. The ArrayList reference is passed as an argument to your recursion call each time, but it still points to the same ArrayList. When you then put it into the hashmap, you are storing multiple references to the same, single, original ArrayList.
Therefore use ArrayList.clone() before adding it to the master list. Better still, store an immutable collection to ensure your hash doesn't get messed up in the HashMap:
HashMap<List<String>, Integer> masterList =
new HashMap<List<String>, Integer>();
...
ArrayList<String> tmp = (ArrayList<String>)currList.clone();
List<String> imm = Collections.unmodifiableList(tmp);
masterList.put(imm, imm.size());
"previous ArrayLists are overriden with the new one I'm trying to add, but the previous value remains."
If you do not want the previous values, you might need to do something like this
BEFORE SCENARIO:
final ArrayList<Integer> arrayList = new ArrayList<Integer>();
final HashMap<ArrayList<Integer>, Integer> hashmap = new HashMap<ArrayList<Integer>, Integer>();
arrayList.add(1);
hashmap.put(arrayList, 1);
arrayList.add(2);
hashmap.put(arrayList, 1);
System.out.println(hashmap);
OUTPUT : {[1, 2]=1, [1, 2]=1}
AFTER SCENARIO :
ArrayList<Integer> arrayList = new ArrayList<Integer>();
final HashMap<ArrayList<Integer>, Integer> hashmap = new HashMap<ArrayList<Integer>, Integer>();
arrayList.add(1);
hashmap.put(arrayList, 1);
arrayList = new ArrayList<Integer>();
arrayList.add(2);
hashmap.put(arrayList, 1);
System.out.println(hashmap);
OUTPUT : {[1]=1, [2]=1}
Having trouble with the containsKey and get method, also not sure how to iterate through the hashtable keys and values, I want to iterate through and add the keys with the value of true to the solution list
1st error: The method containsKey(int) is undefined for the type hashTable
2nd error: Can only iterate over an array or an instance of java.lang.Iterable
3rd error: The method get(int) is undefined for the type hashTable
package practice;
import java.util.*;
/*
You are given an integer array, where all numbers except for TWO numbers appear even number of times.
Q: Find out the two numbers which appear odd number of times.
*/
public class hashTable{
public static void main(String[] args){
int[] test = {2, 2, 5, 7, 4, 4};
List<Integer> solution = new ArrayList<Integer>();
Hashtable<Integer, Boolean> ht = new Hashtable<Integer, Boolean>();
Boolean check = true;
for (int item : test){
//error if (!containsKey(item)){
check = true;
} else{
check = false;
ht.put(item, check);
}
}
//error for (int item : ht){
//error if (get(item) == true){
solution.add(item);
}
}
System.out.println("the result is");
System.out.println(solution);
}
}
The issue would seem that you are using a generic type without providing the generic information. If you put #SuppressWarnings("unchecked") (or something along those lines, do not have an IDE to test), the warning should go away. That being said, I would advise against that.
Ideally, you should provide generic information and do as #BackSlash suggested: Hashtable<Integer, String> ht = new Hashtable<Integer, String>();. This will provide the compiler with the generic information it needs and makes your collection type safe which is something you usually want.
That being said, I would recommend a different approach:
Iterate over your array.
Create a hash table: HashTable<Integer, Boolean>.
If the number you are iterating on exists in the hash table, then apply the not operator on the value at HashTable[number].
If not, add a new entry and set the boolean value to false.
Seeing your comment, you could try something like so:
Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
int[] nums = ...
for(Integer number : nums)
{
if(table.containsKey(number))
{
table.put(number, !table.get(number));
}
else
{
table.put(number, false);
}
}
This question already has answers here:
How do I convert a Map to List in Java?
(13 answers)
Closed 8 years ago.
I have this code :
ArrayList<Integer> users = new ArrayList<Integer>();
Map <String,Object> hashMap = new HashMap <String,Object> ();
hashMap.put("users",user);
// now I want to get users as array list
hashMap.get("users")[i];//error
How to users as array ? thank you
List<Integer> users = new ArrayList<Integer>();
Map<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("users",user);
....
....
....
List<Integer> users = (List<Integer>)hashMap.get("users"); //assuming this is another method and 'users' is not defined here yet
Integer[] usersArray = users.toArray(new Integer[users.size()]);
System.out.println("" + usersArray[i]);
Please note that this is an atrocity and you shouldn't be storing that List as an Object, you are pretty much circumventing what Generics are for.
This code will work if you want to access it as an ArrayList:
List<Integer> users = new ArrayList<Integer>();
Map<String, List<Integer>> hashMap = new HashMap<String, List<Integer>> ();
hashMap.put("users",users);
hashMap.get("users");
Your code won't work since you were storing it as an Object. So you would need a cast. And even then you use [] for arrays, not ArrayLists
If you want to use it as an array you can change the last line to:
hashMap.get("users").toArray()
And then you can use [1], or just do .get(1) on the initial code.
Alternatively, if you want to use hashMap as a property bag as someone validly mentioned you would need to do a cast:
((ArrayList<Integer>) hashMap.get("users"))
Then you can use users as an ArrayList as you are getting an Object by default from the HashMap.
You can try something like following
List<Users> usersList = new ArrayList<>();
Map<String,List<Users>> hashMap = new HashMap <> ();
hashMap.put("user",usersList);
Now
hashMap.get("user")
Will return a List of Users, Now you can use
hashMap.get("user").get(0); // to get 0th index user
Because it is ArrayList and not array,You can get it like this-
public static void main(String args[]) throws Exception
{
ArrayList<Integer> users = new ArrayList<Integer>();
users.add(5);
users.add(10);
Map <String,Object> hashMap = new HashMap <String,Object> ();
hashMap.put("users",users);
ArrayList<Integer> no = ((ArrayList<Integer>) hashMap.get("users"));
for (Integer integer : no) {
System.out.println(integer);
}
}
output-
5
10
Now to convert ArrayList to Array -
Integer[] arr = no.toArray(new Integer[no.size()]);
I want to make arrayList object in java that work as two dimentional array. My question is how can we access value from specific dimention from arrayList.
in two dimentional array, if i want to access value then it can be as m[i][j].
But in arraylist how can i do that ?
You mean something like a List in a List??
May be something like...
List<List<...>> twoDList = new ArrayList<>();
i want to make a List, in which each List key contains another List inside it
It should more like you want some kind of Map, which is basically a key/value pair.
Map<String, List<String>> mapValues = new HashMap<>(25);
List<String> listOfValues = ...;
//...
mapValues.put("A unique key for this list", listOfValues);
//...
List<String> thatListOfValues = mapValues.get("A unique key for this list");
List<List<Integer>> list = new ArrayList<List<Integer>>();
list.add(new ArrayList<Integer>());
list.add(new ArrayList<Integer>());
list.get(0).add(5);
list.get(1).add(6);
for(List<Integer> listiter : list)
{
for(Integer integer : listiter)
{
System.out.println("" + integer);
}
}
This way you can get the items like
list.get(1).get(0); //second dimension list -> integer
EDIT:
Although it is true that you can use a Map if you are trying to use numeric indices for example for each list, like so:
Map<Integer, List<YourObject>> map = new HashMap<Integer, List<YourObject>>();
map.put(0, new ArrayList<YourObject>());
map.put(5, new ArrayList<YourObject>());
map.get(0).add(new YourObject("Hello"));
map.get(5).add(new YourObject("World"));
for(Integer integer : map.keySet())
{
for(YourObject yourObject : map.get(integer))
{
yourObject.print(); //example method
System.out.println(" ");
}
}
Although even then the accessing of Lists would be the same as before,
map.get(0).get(1); //List -> value at index
Obviously you don't need to use Integers as the generic type parameter, that's just a placeholder type.
The solution like List<List<..>> is slow then you should use one dimention array like
// Two dimentions: m and n
List<String> arr = new ArrayList<String>(m*n);
for (int i=0; i< m; ++i) {
for (int j=0; j<n; ++j) {
String str=arr.get(i*n + j);
//You code here
}
}
Memory is an important consideration here.
It can be acceptable to model a 2D (or higher dimension) array using a 1D container. (This is how the VARIANT SAFEARRAY of Microsoft's COM works.) But, consider this carefully if the number of elements is large; especially if the container allocates a contiguous memory block. Using something like List<List<... will model a jagged-edged matrix and can fragment your memory.
With the 1D approach, you can use the get(index) method on the ArrayList appropriately transformed:
Given the (i)th row and (j)th column, transform using index = i * rows + j where rows is the number of rows in your matrix.
An arraylist is not an object to make a 2 dimentional arrays. However you can use it anyway :
You can use :
new ArrayList<ArrayList<Object>>; //or
new ArrayList<Object[]>;
But you should implement your own matrix class because you will probably have some check to do and a function get(int row, int column) would be cool
Also consider Table collection provided by Google Guava library. ArrayTable is an implementation based on 2D array.
You cane define like this
1>
List<Object[]> list = new ArrayList<Object[]>();
Fetching
list.get(i)[j];
2>
List<Map<Integer,Object>> list = new ArrayList<Map<Integer,Object>>();
Fetching
list.get(i).get(j);
I have 2 arraylists contained objects like this:
1st arraylist contains string and double : [a 1.1, b 1.2, d 0.4, g 1.9, f 0.5 and so on...]
2nd arraylist contains string, double and int : [b 0.1 2, f 1.1 5, g 2.3 1, a 1.1 2 and so on...]
2nd arraylist may contain either same or greater or lesser number of items in it than 1st one but all its string property values will be any of those which are only present in 1st one's string property.
All I need to sort the 2nd arraylist by the string property according to the order of 1st arraylist string property. 1st arraylist is already in order and if I sort the 2nd one then the expected output will be:
[a 1.1 2, b 0.1 2, g 2.3 1, f 1.1 5 .....]
I've seen some questions and answers with comparator but all of them are doing sort with one type of arraylist. But here I have 2 types of arraylist and I really don't know how to do it!
So if you have any idea please share it with me and if possible share some sample code.
I am a novice in stackoverflow as well as have not much experience in Java. I'm having a great trouble with this situation. After googling and searching particularly in stackoverflow but couldn't get any helpful idea to go through. I've explained the situation above and please pardon me if I made any mistake!
Thanks!
This is fairly simple. Here's some pseudo-Java, which assumes there are no duplicate keys in list1, and does not require any external libraries.
Assuming the following...
class List1Item {
String stringValue;
double doubleValue;
};
class List2Item {
String stringValue;
double doubleValue;
int intValue;
};
List<List1Item> list1 = new ArrayList<>();
List<List2Item> list2 = new ArrayList<>();
The general approach is to build a mapping between each key value and its position in the first list.
// Map to hold list1 key-to-position association
Map<String,Integer> sortKeys = new HashMap<>();
// Populate the key-to-position map with keys from list1
int pos=0;
for (List1Item i : list1)
sortKeys.put(i.stringValue,pos++);
Then use the map to sort list2 items by the position of the key in list1:
// Define a comparator that will use the map to sort list2 keys
Comparator<List2Item> comp = new Comparator<List2Item>()
{
public int compare(List2Item v1, List2Item v2)
{
return sortKeys.get(v1.stringValue).compareTo(sortKeys.get(v2.stringValue));
}
}
Collections.sort(list2,comp);
Lets assume the object in list1 and list2 are of type Foo and Bar and they both implement a method getString() which returns the string property. Like you said, the string values in list 1 are unique.
ArrayList<Foo> list1 = new ArrayList<Foo>();
ArrayList<Bar> list2 = new ArrayList<Bar>();
final HashMap<String, Integer> positions = new HashMap<String, Integer>();
for(int i=0;i<list1.size();i++){
positions.put(obj.getString(), i);
}
Collections.sort(list2, new Comparator<Bar>(){
public int compare(Bar obj1, Bar obj2){
return positions.get(obj2.getString()) - positions.get(obj1.getString());
}
});
This is a pretty complicated problem, and there isn't going to be any truly simple solution.
The simplest thing I can think of depends on the third-party library Guava. (Disclosure: I am a contributor.)
Let's call the first object type Foo and the second object type Bar, since you haven't named them yet. I'm also assuming that the String fields of the Bars are unique in the second list.
List<String> stringOrder = new ArrayList<String>();
for (Bar bar : list2) {
stringOrder.add(bar.getString());
}
Ordering<String> stringComparator = Ordering.explicit(stringOrder);
// construct a String comparator based on that ordering
Ordering<Foo> fooOrdering = stringComparator.onResultOf(
new Function<Foo, String>() {
public String apply(Foo foo) {
return foo.getString();
}
});
Collections.sort(list1, fooOrdering);