Java - Array index out of range - Vector? - java

I'm testing a method that adds a linked list of hash pairs inside a vector. Although, I'm running into a IndexOutOfBounds but I'm having trouble understanding where the problem exists.
import java.util.*;
class HashPair<K, E> {
K key;
E element;
}
public class Test4<K, E> {
private Vector<LinkedList<HashPair<K, E>>> table;
public Test4(int tableSize) {
if (tableSize <= 0)
throw new IllegalArgumentException("Table Size must be positive");
table = new Vector<LinkedList<HashPair<K, E>>>(tableSize);
}
public E put(K key, E element) {
if (key == null || element == null)
throw new NullPointerException("Key or element is null");
int i = hash(key);
LinkedList<HashPair<K, E>> onelist = table.get(i);
ListIterator<HashPair<K, E>> cursor = onelist.listIterator();
HashPair<K, E> pair;
E answer = null;
while (cursor.hasNext()) {
pair = cursor.next();
if (pair.key.equals(key)) {
answer = pair.element;
pair.element = element;
return answer;
}
}
pair = new HashPair<K, E>();
pair.key = key;
pair.element = element;
onelist.addFirst(pair);
return answer;
}
private int hash(K key) {
return Math.abs(key.hashCode() % table.capacity());
}
public static void main(String[] args) {
Test4<Integer, Integer> obj = new Test4<Integer, Integer>(10);
obj.put(0, 10);
}
}
My compiler says that the problem is here:
LinkedList<HashPair<K, E>> onelist = table.get(i);
From what I understand is that I'm trying to get the table index of i which is a hash value generated from the hash(K key) method. So in my main method if I set the key to 0 as an example? Why is the index out of range?
Here is the exception
Exception in thread "main" 0java.lang.ArrayIndexOutOfBoundsException:
Array index out of range: 0
at java.util.Vector.get(Vector.java:748)
at Test4.put(Test4.java:24)
at Test4.main(Test4.java:55)

The problem here is that you are considering the capacity of a vector to be the number of elements in the vector. This is not what capacity of a collection represents.
The capacity of a collection in the standard Java libraries is the size of the internal array used by that collection. The number of elements in the collection, however, is represented by size.
Whenever an element is added to/removed from such a collection, the size property is modified. This does not affect the capacity of the collection unless the internal array needs to be resized.
The solution: modify hash() to the following:
private int hash(K key) {
return Math.abs(key.hashCode() % table.size());
}
And make sure that the table vector contains at least one element before calling hash and table.get.
I presume that you are creating an implementation of a HashMap with buckets. If you are, then ponder this: How can you go about storing a value in a bucket if there aren't any buckets? You need to have at least one bucket before trying to get a bucket.

It seems your code is getting stuck at line 748, which is:
LinkedList<HashPair<K, E>> onelist = table.get(i);
The description Array index out of range: 0 means you're trying to get an object at slot '0', when there is no such slot available at the time. In short: your vector is empty. And by looking at your code, the reason becomes pretty evident. The only treatment this Vector called table receives before Test4.put() is called gets down to this at line 15:
table = new Vector<LinkedList<HashPair<K, E>>>(tableSize);
So, yes, you're properly creating an object and initializing a variable, you are even specifying a default capacity, but you never added something into your brand new Vector, and both lists and vectors do require to be filled manually with stuff first. Keep on mind that this "capacity" refers to how much stuff is this Vector supposed to hold without need to resize the array it uses internally. It gives me the impression you are trying to create a class whose objects have a behavior like HashMaps, but I can't wrap my mind around the need of using a Vector of LinkedLists of KeyPairs when just a single collection of KeyPairs should be enough unless... wait, what is that hash() method doing? Oh... ohh... oh, I see what you did there.
So, right, the solution. As your Vector is properly created but empty, you need to fill it with whatever it is supposed to hold. In this case, it holds LinkedLists of KeyPairs, so let's fill it with just enough of them to hold the capacity you set through the constructor. This modification to the constructor should do the thing:
public Test4(int tableSize) {
if (tableSize <= 0)
throw new IllegalArgumentException("Table Size must be positive");
table = new Vector<LinkedList<HashPair<K, E>>>(tableSize);
//Prepare the fast lookup table (at least that's what I think it could be called)
for (int i = 0; i < tableSize; i++) {
table.add(new LinkedList<HashPair<K, E>>());
}
}
And that's pretty much it. I even tested it here just to be sure it worked fine after my patch.
Hope this helps you.
PS: Splitting your structure in n pieces to speedup search/store? I like the idea.

Related

Comparison Error when Storing values in a List, Boolean Map

I have a fully working version of MineSweeper implemented in Java. However, I am trying to add an additional feature that updates a Map to store the indexes of the locations of the mines within a 2D array. For example, if location [x][y] holds a mine, I am storing a linked list containing x and y, which maps to a boolean that is true to indicate that the space holds a mine. (This feature is seemingly trivial, but I am just doing this to practice with Collections in Java.)
My relevant private instance variables include:
public Class World{ ...
private LinkedList<Integer> index;
private Map<LinkedList<Integer>, Boolean> revealed;
"index" is the list to be stored in the map as the key for each boolean.
In my constructor I have:
public World(){ ...
tileArr = new Tile[worldWidth][worldHeight];
revealed = new TreeMap<LinkedList<Integer>, Boolean>();
index = new LinkedList<Integer>();
... }
Now, in the method in which I place the mines, I have the following:
private void placeBomb(){
int x = ran.nextInt(worldWidth); //Random stream
int y = ran.nextInt(worldHeight); //Random stream
if (!tileArr[x][y].isBomb()){
tileArr[x][y].setBomb(true);
index.add(x); //ADDED COMPONENT
index.add(y);
revealed.put(index, true);
index.remove(x);
index.remove(y); //END OF ADDED COMPONENT
} else placeBomb();
}
Without the marked added component my program runs fine, and I have a fully working game. However, this addition gives me the following error.
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList
cannot be cast to java.lang.Comparable
If anyone could help point out where this error might be, it would be very helpful! This is solely for additional practice with collections and is not required to run the game.
There are actually about 3 issues here. One that you know about, one that you don't and a third which is just that using LinkedList as a key for a map is clunky.
The ClassCastException happens because TreeMap is a sorted set and requires that every key in it implement the Comparable interface, or else you have to provide a custom Comparator. LinkedList doesn't implement Comparable, so you get an exception. The solution here could be to use a different map, like HashMap, or you could write a custom Comparator.
A custom Comparator could be like this:
revealed = new TreeMap<List<Integer>, Boolean>(
// sort by x value first
Comparator.comparing( list -> list.get(0) )
// then sort by y if both x values are the same
.thenComparing( list -> list.get(1) )
);
(And I felt compelled to include this, which is a more robust example that isn't dependent on specific elements at specific indexes):
revealed = new TreeMap<>(new Comparator<List<Integer>>() {
#Override
public int compare(List<Integer> lhs, List<Integer> rhs) {
int sizeComp = Integer.compare(lhs.size(), rhs.size());
if (sizeComp != 0) {
return sizeComp;
}
Iterator<Integer> lhsIter = lhs.iterator();
Iterator<Integer> rhsIter = rhs.iterator();
while ( lhsIter.hasNext() && rhsIter.hasNext() ) {
int intComp = lhsIter.next().compareTo( rhsIter.next() );
if (intComp != 0) {
return intComp;
}
}
return 0;
}
});
The issue that you don't know about is that you're only ever adding one LinkedList to the map:
index.add(x);
index.add(y);
// putting index in to the map
// without making a copy
revealed.put(index, true);
// modifying index immediately
// afterwards
index.remove(x);
index.remove(y);
This is unspecified behavior, because you put the key in, then modify it. The documentation for Map says the following about this:
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
What will actually happen (for TreeMap) is that you are always erasing the previous mapping. (For example, the first time you call put, let's say x=0 and y=0. Then the next time around, you set the list so that x=1 and y=1. This also modifies the list inside the map, so that when put is called, it finds there was already a key with x=1 and y=1 and replaces the mapping.)
So you could fix this by saying something like either of the following:
// copying the List called index
revealed.put(new LinkedList<>(index), true);
// this makes more sense to me
revealed.put(Arrays.asList(x, y), true);
However, this leads me to the 3rd point.
There are better ways to do this, if you want practice with collections. One way would be to use a Map<Integer, Map<Integer, Boolean>>, like this:
Map<Integer, Map<Integer, Boolean>> revealed = new HashMap<>();
{
revealed.computeIfAbsent(x, HashMap::new).put(y, true);
// the preceding line is the same as saying
// Map<Integer, Boolean> yMap = revealed.get(x);
// if (yMap == null) {
// yMap = new HashMap<>();
// revealed.put(x, yMap);
// }
// yMap.put(y, true);
}
That is basically like a 2D array, but with a HashMap. (It could make sense if you had a very, very large game board.)
And judging by your description, it sounds like you already know that you could just make a boolean isRevealed; variable in the Tile class.
From the spec of a treemap gives me this:
The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
The Java Linkedlist can not be compared just like that. You have to give it a way to compare them or just use another type of map, that does not need sorting.

Set vs List when need both unique elements and access by index

I need to keep a unique list of elements seen and I also need to pick random one from them from time to time. There are two simple ways for me to do this.
Keep elements seen in a Set - that gives me uniqueness of elements. When there is a need to pick random one, do the following:
elementsSeen.toArray()[random.nextInt(elementsSeen.size())]
Keep elements seen in a List - this way no need to convert to array as there is the get() function for when I need to ask for a random one. But here I would need to do this when adding.
if (elementsSeen.indexOf(element)==-1) {elementsSeen.add(element);}
So my question is which way would be more efficient? Is converting to array more consuming or is indexOf worse? What if attempting to add an element is done 10 or 100 or 1000 times more often?
I am interested in how to combine functionality of a list (access by index) with that of a set (unique adding) in the most performance effective way.
If using more memory is not a problem then you can get the best of both by using both list and set inside a wrapper:
public class MyContainer<T> {
private final Set<T> set = new HashSet<>();
private final List<T> list = new ArrayList<>();
public void add(T e) {
if (set.add(e)) {
list.add(e);
}
}
public T getRandomElement() {
return list.get(ThreadLocalRandom.current().nextInt(list.size()));
}
// other methods as needed ...
}
HashSet and TreeSet both extend AbstractCollection, which includes the toArray() implementation as shown below:
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
As you can see, its responsible for allocating the space for an array, as well as creating an Iterator object for copying. So, for a Set, adding is O(1), but retrieving a random element will be O(N) because of the element copy operation.
A List, on the other hand, allows you quick access to a specific index in the backing array, but doesn't guarantee uniqueness. You would have to re-implement the add, remove and associated methods to guarantee uniqueness on insert. Adding a unique element will be O(N), but retrieval will be O(1).
So, it really depends on which area is your potential high usage point. Are the add/remove methods going to be heavily used, with random access used sparingly? Or is this going to be a container for which retrieval is most important, since few elements will be added or removed over the lifetime of the program?
If the former, I'd suggest using the Set with toArray(). If the latter, it may be beneficial for you to implement a unique List to take advantage to the fast retrieval. The significant downside is add contains many edge cases for which the standard Java library takes great care to work with in an efficient manner. Will your implementation be up to the same standards?
Write some test code and put in some realistic values for your use case. Neither of the methods are so complex that it's not worth the effort, if performance is a real issue for you.
I tried that quickly, based on the exact two methods you described, and it appears that the Set implementation will be quicker if you are adding considerably more than you are retrieving, due to the slowness of the indexOf method. But I really recommend that you do the tests yourself - you're the only person who knows what the details are likely to be.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class SetVsListTest<E> {
private static Random random = new Random();
private Set<E> elementSet;
private List<E> elementList;
public SetVsListTest() {
elementSet = new HashSet<>();
elementList = new ArrayList<>();
}
private void listAdd(E element) {
if (elementList.indexOf(element) == -1) {
elementList.add(element);
}
}
private void setAdd(E element) {
elementSet.add(element);
}
private E listGetRandom() {
return elementList.get(random.nextInt(elementList.size()));
}
#SuppressWarnings("unchecked")
private E setGetRandom() {
return (E) elementSet.toArray()[random.nextInt(elementSet.size())];
}
public static void main(String[] args) {
SetVsListTest<Integer> test;
List<Integer> testData = new ArrayList<>();
int testDataSize = 100_000;
int[] addToRetrieveRatios = new int[] { 10, 100, 1000, 10000 };
for (int i = 0; i < testDataSize; i++) {
/*
* Add 1/5 of the total possible number of elements so that we will
* have (on average) 5 duplicates of each number. Adjust this to
* whatever is most realistic
*/
testData.add(random.nextInt(testDataSize / 5));
}
for (int addToRetrieveRatio : addToRetrieveRatios) {
/*
* Test the list method
*/
test = new SetVsListTest<>();
long t1 = System.nanoTime();
for(int i=0;i<testDataSize; i++) {
// Use == 1 here because we don't want to get from an empty collection
if(i%addToRetrieveRatio == 1) {
test.listGetRandom();
} else {
test.listAdd(testData.get(i));
}
}
long t2 = System.nanoTime();
System.out.println(((t2-t1)/1000000L)+" ms for list method with add/retrieve ratio "+addToRetrieveRatio);
/*
* Test the set method
*/
test = new SetVsListTest<>();
t1 = System.nanoTime();
for(int i=0;i<testDataSize; i++) {
// Use == 1 here because we don't want to get from an empty collection
if(i%addToRetrieveRatio == 1) {
test.setGetRandom();
} else {
test.setAdd(testData.get(i));
}
}
t2 = System.nanoTime();
System.out.println(((t2-t1)/1000000L)+" ms for set method with add/retrieve ratio "+addToRetrieveRatio);
}
}
}
Output on my machine was:
819 ms for list method with add/retrieve ratio 10
1204 ms for set method with add/retrieve ratio 10
1547 ms for list method with add/retrieve ratio 100
133 ms for set method with add/retrieve ratio 100
1571 ms for list method with add/retrieve ratio 1000
23 ms for set method with add/retrieve ratio 1000
1542 ms for list method with add/retrieve ratio 10000
5 ms for set method with add/retrieve ratio 10000
You could extend HashSet and track the changes to it, maintaining a current array of all entries.
Here I keep a copy of the array and adjust it every time the set changes. For a more robust (but more costly) solution you could use toArray in your pick method.
class PickableSet<T> extends HashSet<T> {
private T[] asArray = (T[]) this.toArray();
private void dirty() {
asArray = (T[]) this.toArray();
}
public T pick(int which) {
return asArray[which];
}
#Override
public boolean add(T t) {
boolean added = super.add(t);
dirty();
return added;
}
#Override
public boolean remove(Object o) {
boolean removed = super.remove(o);
dirty();
return removed;
}
}
Note that this will not recognise changes to the set if removed by an Iterator - you will need to handle that some other way.
So my question is which way would be more efficient?
Quite a difficult question to answer depending on what one does more, insert or select at random?
We need to look at the Big O for each of the operations. In this case (best cases):
Set: Insert O(1)
Set: toArray O(n) (I'd assume)
Array: Access O(1)
vs
List: Contains O(n)
List: Insert O(1)
List: Access O(1)
So:
Set: Insert: O(1), Access O(n)
List: Insert: O(n), Access O(1)
So in the best case they are much of a muchness with Set winning if you insert more than you select, and List if the reverse is true.
Now the evil answer - Select one (the one that best represents the problem (so Set IMO)), wrap it well and run with it. If it is too slow then deal with it later, and when you do deal with it, look at the problem space. Does your data change often? No, cache the array.
It depends what you value more.
List implementations in Java normally makes use of an array or a linked list. That means inserting and searching for an index is fast, but searching for a specific element will require looping thought the list and comparing each element until the element is found.
Set implementations in Java mainly makes use of an array, the hashCode method and the equals method. So a set is more taxing when you want to insert, but trumps list when it comes to looking for an element. As a set doesn't guarantee the order of the elements in the structure, you will not be able to get an element by index. You can use an ordered set, but this brings with it latency on the insert due to the sort.
If you are going to be working with indexes directly, then you may have to use a List because the order that element will be placed into Set.toArray() changes as you add elements to the Set.
Hope this helps :)

How to put a element in specific location of array list

I want to add a element in specific location of array list For that i tried to initialize the array list with inital capacity.
import java.util.ArrayList;
public class AddInArrayList{
public static void main(String[] args) {
ArrayList list = new ArrayList(4);
Object obj1 = new Object();
list.add(1, obj1);
}
}
OUTPUT
Exception in thread "main" java.lang.IndexOutOfBoundsException:
Index: 1, Size: 0
at java.util.ArrayList.add(ArrayList.java:359)
at AddInArrayList.main(AddInArrayList.java:7)
Is There any way to add a element by specific index location ?
You are confused about the meaning of capacity: the number you pass to the constructor does not set the inital list size.
You can't insert an element at index 1 of an empty list because list slots cannot be empty. If you wanted a function that expands the list before inserting at an index greater than its length, you could use:
static void addAtPos(List list, int index, Object o) {
while (list.size() < index) {
list.add(null);
}
list.add(index, o);
}
That said, ArrayLists are based on arrays which do not perform well with mid-insertion. So a different data structure will almost certainly be better suited to your problem, but you'd have to let us know what you're trying to achieve.
Arrays will not let you to perform insertion at an index which is greater than array.size.
So if you want to associate each item with a number/index it is better to use maps.
Map map = new HashMap<Integer, Object>();
Object obj1 = new Object();
map.put(1, obj1);
You're getting IndexOutOfBoundsException because when you call add(index, value), the value has to be not less than 0 and not bigger than list.size()-1. In your case it should be add(0, obj1).
initial capacity will be used only to set the initial "buffer" size of underlying array. so after calling new ArrayList(4) you list is still empty.
If you know your List will contain about 10_000 elements, create the ArrayList instance with intial capacity c = 10_000 + x. In this way you will avoid expensive ArrayList#grow(newcapacity) (Java 8) calls.
The method ArrayList#add(position, element) could be also called ArrayList#addAndMoveOtherToTheRight(position, element)

Java ArrayList IndexOutOfBoundsException despite giving an initial capacity

When I do
ArrayList<Integer> arr = new ArrayList<Integer>(10);
arr.set(0, 1);
Java gives me
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.set(Unknown Source)
at HelloWorld.main(HelloWorld.java:13)
Is there an easy way I can pre-reserve the size of ArrayList and then use the indices immediately, just like arrays?
How about this:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
This will initialize arr with 10 zero's. Then you can feel free to use the indexes immediately.
Here's the source from ArrayList:
The constructor:
public ArrayList(int initialCapacity)
{
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
You called set(int, E):
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Set calls rangeCheck(int):
private void rangeCheck(int index)
{
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
It may be subtle, but when you called the constructor, despite initializing an Object[], you did not initialize size. Hence, from rangeCheck, you get the IndexOutOfBoundsException, since size is 0. Instead of using set(int, E), you can use add(E e) (adds e of type E to the end of the list, in your case: add(1)) and this won't occur. Or, if it suits you, you could initialize all elements to 0 as suggested in another answer.
I believe the issue here is that although you have suggested the allocated space of entries in the Array, you have not actually created entries.
What does arr.size() return?
I think you need to use the add(T) method instead.
Programming aside, what you are trying to do here is illogical.
Imagine an empty egg carton with space for ten eggs. That is more or less what you have created. Then you tell a super-precise-and-annoying-which-does-exactly-what-you-tell-him robot to replace the 0th egg with another egg. The robot reports an error. Why? He can't replace the 0th egg, because there is no egg there! There is a space reserved for 10 eggs, but there are really no eggs inside!
You could use arr.add(1), which will add 1 in the first empty cell, i.e. the 0-indexed one.
Or you could create your own list:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
Then:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
Prints:
[null, null, null, 1, null]
This is not an Java-specific answer but an data structure answer.
You are confusing the Capacity concept with the Count (or Size) one.
Capacity is when you tell the list to reserve/preallocate a number of slots in advance (in this ArrayList case, you are saying to it create an array of 10 positions) in its' internal storage. When this happens, the list still does not have any items.
Size (or Count) is the quantity of items the list really have. In your code, you really doesn't added any item - so the IndexOutOfBoundException is deserved.
While you can't do what you want with arraylist, there is another option: Arrays.asList()
Capacity is used to prepare ArrayLists for expansion. Take the loop
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list starts off with a capacity of 10. Therefore it holds a new Integer[10] inside. As the loop adds to the list, the integers are added to that array. When the array is filled and another number is added, a new array is allocated twice the size of the old one, and the old values are copied to the new ones. Adding an item is O(1) at best, and O(N) at worst. But adding N items will take about 2*1024 individual assignments: amortized linear time.
Capacity isn't size. If you haven't added to the array list yet, the size will be zero, and attempting to write into the 3rd element will fail.

Can't add to an array list

I have the oddest problem, probably with a simple solution.
I have created and initialized a list and then proceeded to create 4 objects of the list's type. In the constructor of these they place themselves in the list. Or at least are supposed to. I always get an out of bound exception and I cant figure out why. I set the list to have a size of 402 (for all possible VK values) but in the console and debug it always says it has size 0, no matter how large or empty I set it too....
public class InputHandler implements KeyListener
{
public static List<Key> keyList = new ArrayList<Key>(KeyEvent.KEY_LAST);
public Key up = new Key(KeyEvent.VK_UP);
public Key down = new Key(KeyEvent.VK_DOWN);
public Key left = new Key(KeyEvent.VK_LEFT);
public Key right = new Key(KeyEvent.VK_RIGHT);
public class Key
{
public int keyCode;
public Key(int defaultCode)
{
this.keyCode = defaultCode;
keyList.add(keyCode,this);
}
public Key reMapKey(int newKey)
{
keyList.remove(keyCode);
keyList.set(newKey, this);
this.keyCode = newKey;
return this;
}
}
}
There is more to the code but I attempted to SSCCE it.
The only info of value from the console is this:
Exception in thread "RogueLoveMainThread" java.lang.IndexOutOfBoundsException: Index: 38, Size: 0
Much apologies for my stupidity
You've created a new ArrayList with a capacity of 402, but it's still got a size of 0 after the constructor call. From the docs of the constructor call you're using:
public ArrayList(int initialCapacity)
Constructs an empty list with the specified initial capacity.
Parameters:
initialCapacity - the initial capacity of the list
And from the docs of ArrayList itself:
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically.
The capacity is not the size.
So, some options:
Populate the list with null entries until you have got the size you want
Use an array instead of a list (after all, you only need it to be a fixed size, right?)
Use a Map<Integer, Key> instead
keyList.add(keyCode, this) inserts at the position of keyCode. As your list is still empty (size 0) you cannot insert at any position position greater than 0.
You might want to have map codes to keys, do you? There is a Map<K, V> for this:
static Map<Integer, Key> keyMap = new TreeMap<>();
public Key(int defaultCode) {
keyMap.add(keyCode, this);
}
If you need a key by its code, you can receive it from the Map as follows:
keyMap.get(keyCode);

Categories