Iterating through hashtable and using the get and containsKey methods - java

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);
}
}

Related

Why this code is not giving the unique values? I implemented hashmap here

why this code is not giving me the desired output?As we use hashmaps to implement key value pairs
and the keys are unique. So this can remove the duplicate elements from the array. But instead of removing duplicate elements it is removing some of the actual elements.
package hashmaps;
import java.util.HashMap;
public class HashMap01 {
public static void main(String[] args) {
int[] arr = {1,2,2,4,5,5,5,7,66,65,65};
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0; i<arr.length; i++){
if(map.containsKey(arr[i])){
map.remove(arr[i]);
} else {
map.put(arr[i],i);
}
}
map.forEach((k,v)-> System.out.print(k+" "));
}
}
I want
1,2,4,5,7,66,65
But getting 1,66,4,5,7
map.remove(arr[i]); removes the entry, and your code does not put any new entry back in its place.
The simplest fix is just to replace
if(map.containsKey(arr[i])){
map.remove(arr[i]);
} else {
map.put(arr[i],i);
}
with
map.put(arr[i],i);
As an addendum to Louis' answer, you don't need the a map here, because you don't use the value.
Just use a HashSet:
HashSet<Integer> set = new HashSet<>();
for(int i=0; i<arr.length; i++){
set.add(arr[i]);
}
// Or:
// HashSet<Integer> set = Arrays.stream(arr).boxed().collect(Collectors.toCollection(HashSet::new));
set.forEach(k-> System.out.print(k+" "));
Actually, the way HashSet is implemented is just using a HashMap: the values you add to the Set are the map keys; the value stored for each key is some arbitrary value. See this question for more details.
Note that with either a HashSet or HashMap you don't get a reliable iteration order. If you want the entries to appear in the encounter order, use a LinkedHashSet (/LinkedHashMap).

Check if an ArrayList contains the same element as another ArrayList

I have used some other answers to get a solution to my problem. But I am wondering if there is a way to improve this further?
// Copy the masterList ArrayList and then sort in ascending order and then make a third
// ArrayList and loop through to add the 8 lowest values to this list.
ArrayList<Integer> sortedList = new ArrayList<>(Calculator.masterList);
Collections.sort(sortedList);
ArrayList<Integer> lowEight = new ArrayList<>();
for (int i = 0; i < 8; i++) {
lowEight.add(sortedList.get(i));
}
// Set TextView as the value of index 0 in masterList ArrayList, check if lowEight
// ArrayList contains the element that is the same as masterList index 0 and if
// so highlight s1 textview green.
s1.setText("Score 1 is " + String.format("%d", Calculator.masterList.get(0)));
if (lowEight.contains(Calculator.masterList.get(0))) {
s1.setBackgroundColor(Color.GREEN);
}
This works to an extent by highlighting the values that are in both masterList and lowEight but for example if the number 7 is in lowEight and appears 9 times in masterList it will highlight all 9 occurences. Is there a way to move the exact object from masterList to sortedList and then to lowEight and then a method to check the object and not just the value?
Let me provide a more concise example of what you're asking. Let us take the following code:
ArrayList<Integer> list1 = new ArrayList<Integer>() {
{
add(5);
add(5);
}
};
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(list1.get(0));
list1.forEach((i) -> System.out.println(list2.contains(i)));
The output is:
true
true
But you would expect it to be:
true
false
Because the first and second element are different objects. The problem here is that although they are different objects, they are equal objects. The way the Integer class is written in Java, any Integer is equal to another Integer if they represent the same value. When you run the contains() method, it sees that the list does indeed contain an object equal to the one you provided (in this case they both represent a value of 5), and so it returns true. So how do we solve this problem? How do we tell one Integer object from another? I would write your own "Integer" class. Something like "MyInteger". Here's a very simple implementation you could use:
public class MyInteger {
private final int i;
public MyInteger(int i) {
this.i = i;
}
public int toInt() {
return i;
}
}
And then when we use it in our ArrayList code:
ArrayList<MyInteger> list1 = new ArrayList<MyInteger>() {
{
add(new MyInteger(5));
add(new MyInteger(5));
}
};
ArrayList<MyInteger> list2 = new ArrayList<>();
list2.add(list1.get(0));
list1.forEach((i) -> System.out.println(list2.contains(i)));
We get our expected output:
true
false
This works because our new MyInteger class implicitly uses the default equals() method, which always returns false. In other words, no two MyInteger objects are ever equal. You can apply this same principle to your code.

Infinite Loop Java for an unfathomable reason

The code is supposed to partition the list into sets. If the ArrayList contains the same strings twice in a row, it will add their indexes to one HashSet otherwise the indexes will be in different HashSets. The point is to put the indexes of all the same strings from the ArrayList in the same HashSet and the indexes of the different strings in different HashSets. For example, the program SHOULD print [[0, 1][2, 3]] but it's stuck in an infinite loop. I put a print statement to verify whether the first two indexes are being added to the HashSet, which they are. The program prints [[0, 1]] instead of the expected result. For some reason, list.get(index1).equals(list.get(index2)) always evaluates to true even though I update the indexes in the loop and the result should be false at the second iteration.
package quiz;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;
public class Question {
public static void main(String[] args) {
Question q = new Question();
ArrayList<String> list2 = new ArrayList<String>();
list2.add("a");
list2.add("a");
list2.add("c");
list2.add("c");
System.out.println(q.answer(list2));
}
public HashSet<HashSet<Integer>> answer(ArrayList<String> list){
HashSet<HashSet<Integer>> hashSet = new HashSet<HashSet<Integer>>();
HashSet<Integer> set = new HashSet<Integer>();
Iterator<String> it = list.iterator();
int index1 = 0;
int index2 = 1;
while (it.hasNext()){
while (list.get(index1).equals(list.get(index2))){
set.add(index1);
set.add(index2);
if (index1<list.size()-2){
index1=index1+1;
index2=index2+1;
}
}
hashSet.add(set);
System.out.println(hashSet);
}
/*else{
set.add(i);
}*/
return hashSet;
}
}
You get an infinite loop because you are using the iterator hasNext() but not using the it.next() afterwards which move the index forward.
In addition, you do not really need the iterator because you are not using the values. You should do something like that:
while(shouldStop)
......
if (index1<list.size()-2){
index1=index1+1;
index2=index2+1;
} else {
shouldStop=true
}
........

Convert 2D arraylist to hashmap in Java

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]}

How to find multiples of the same integer in an arraylist?

My problem is as follows. I have an arraylist of integers. The arraylist contains 5 ints e.g[5,5,3,3,9] or perhaps [2,2,2,2,7]. Many of the arraylists have duplicate values and i'm unsure how to count how many of each of the values exist.
The problem is how to find the duplicate values in the arraylist and count how many of that particular duplicate there are. In the first example [5,5,3,3,9] there are 2 5's and 2 3's. The second example of [2,2,2,2,7] would be only 4 2's. The resulting information i wish to find is if there are any duplicates how many of them there are and what specific integer has been duplicated.
I'm not too sure how to do this in java.
Any help would be much appreciated. Thanks.
To me, the most straightforward answer, would be using the Collections.frequency method. Something along the lines of this:
// Example ArrayList with Integer values
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(2);
intList.add(2);
intList.add(2);
intList.add(2);
intList.add(7);
Set<Integer> noDupes = new HashSet<Integer>();
noDupes.addAll(intList); // Remove duplicates
for (Integer i : noDupes) {
int occurrences = Collections.frequency(intList, i);
System.out.println(i + " occurs " + occurrences + " times.");
}
If you want to, you could map each Integer with its number of occurrences:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer i : noDupes) {
map.put(i, Collections.frequency(intList, i));
}
Two algorithms spring to mind.
Sort it (Collections.sort). Then iterate through easily finding dupes.
Iterate through keeping count in a Map<Integer,Integer> (or Map<Integer,AtomicInteger> for a mutable count). A bit ugly this way.
Either way, coding it should be an instructive exercise. I suggest doing both, and comparing.
Here is a concrete implementation, with test, of what I described in comments to #Tom's answer:
package playground.tests;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.TestCase;
public class DupeCounterTest extends TestCase {
public void testCountDupes() throws Exception {
int[] array = new int[] { 5, 5, 3, 3, 9 };
assertEquals("{3=2, 5=2}", countDupes(array).toString());
}
private Map<Integer, AtomicInteger> countDupes(int[] array) {
Map<Integer, AtomicInteger> map = new HashMap<Integer, AtomicInteger>();
// first create an entry in the map for every value in the array
for (int i : array)
map.put(i, new AtomicInteger());
// now count all occurrences
for (int i : array)
map.get(i).addAndGet(1);
// now get rid of those where no duplicate exists
HashSet<Integer> discards = new HashSet<Integer>();
for (Integer i : map.keySet())
if (map.get(i).get() == 1)
discards.add(i);
for (Integer i : discards)
map.remove(i);
return map;
}
}
Use a Hashmap collection in addition to the array list where
the Hashmap key is the unique array int value and
the Hashmap value to the key is the count of each value encountered.
Walk your array list collecting these values into the hashmap adding a new item when a previous key does not exist and incrementing by 1 the values of keys that do already exist. Then iterate over the Hashmap and print out any keys where the value is > 1.
You can go through the List and put them in a Map with the count. Then it is easy figure out which one is duplicated.
For a cleaner abstraction of what you're doing, you could use the Multiset data structure from guava/google-collections. You may even find you'd rather use it than a List, depending on what you're doing with it (if you don't need the deterministic ordering of a list). You'd use it like this:
Multiset<Integer> multiset = HashMultiset.create(list);
int count = multiset.count(3); // gets the number of 3s that were in the list
In terms of what the above is doing under the covers, it's almost exactly equivalent to the suggestion of building a Map<Integer,AtomicInteger> based on your list.

Categories

Resources