I understand the idea behind a hash table, but the implementation is getting frustrating. I have done some reading and gotten mixed answers. I have read that I could implement a generic array of objects as follows:
TableContainer[] classTable =
(TableContainer<Object,Object>[]) new TableContainer[256];
where tableContainer is:
class TableContainer<key,val>{
Object key = null;
Object val = null;
}
The problem I am having is that when I try to pass the following code in a function:
classTable[i].key = x
I get a null pointer exception. I understand creating generic arrays in java gets messy because of type erasure but I thought the above implementation would work. Is there any way to create a list or array of generics to be utilized as a hashtable? (no hashtable/hashmap classes permitted)
You still have to initialize the object references inside the array before you can use them. Like so
tableContainer[] a = new tableContainer<Whatever, SomeClass>[SIZE];
for ( int i = 0 ; i < a.length; i++ ) {
a[i] = new tableContainer<Whatever, SomeClass>();
}
And of course, you must initialize the array to a size greater than 0, unlike you have in your example.
First of all you are creating an empty array:
new TableContainer[0]
and since you cannot resize arrays over time, it doesn't have much sense. Providing that you actually create an array of some positive size, you must remember one thing: you created an array of references. And by default each array is initialized to default (zero) values, which happens to be null for references.
Thus you need something like this:
classTable = new TableContainer[8];
classTable[0] = new TableContainer();
//...later
if(classTable[0] != null) { //will pass for [0], but not for [1]
classTable[0].key
}
Related
I have an arraylist object catalogHierarchy of type CatalogHierarchy.
The catalogHieriarchy object has three elements. Each element has two attributes like headerName and hierarchyList. The hierarchyList element contains multiple elements of type ProductHierarchy.
I have to set a value of an attribute to Y based on headerName.
The problem I am facing is, I am making the change only for element whose headerName contains text Hierarchy. But after the iteration the catalogHierarchyFlag is set for all other two elements of cloneList object.
Could anyone please help me how to overcome this issue.
ArrayList<CatalogHierarchy> catalogHieriarchy = ... //values from database
List<CatalogHierarchy> cloneList = (ArrayList)catalogHieriarchy.clone();
for(int a=0;a<cloneList.size();a++){
if(cloneList.get(a).getHeaderName().contains("Hierarchy")){
List<ProductHierarchy> catalogHier = cloneList.get(a).getHierarchy();
for(int i = 0 ; i < catalogHier.size() ; i++) {
catalogHier.get(i).setCatalogHierarchyFlag("y");
}
}
}
Read about deep vs. shallow copies. It looks like if you compare your Objects with the == operator, it will return true, indicating that the Objects share the same reference. If you want to create an independent copy of the Object (one that does not share the same reference but that has the same values for the fields) you will have to reimplement the clone() method or provide another method. See the java docs.
The problem is on my second switch case 1: I will put the "arrayEmployees[0]." but it doesn't see my methods in the superclass PersonData or the subclass personLocation. My understanding of polymorhpism is a bit shady as well as the internal "Object" possibility as I just began learning about these so perhaps I am referencing them wrong.
I was given these instructions:
Design a new class called PersonTest with a main method that defines a PersonData object and a PersonLocation object (both without arguments) and two more objects with arguments and store all the objects in an Array for retrieval and modification of instantiated objects (i.e. Array of Objects).
My Actual Code
package lab5;
import java.util.InputMismatchException;
import java.util.Scanner;
public class PersonTest
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
PersonLocation personLocation = new PersonLocation();
PersonData personData = new PersonData();
PersonLocation personLocationOverLoaded = new PersonLocation("Hamilton");
PersonData personDataOverloaded = new PersonData("Stirling", "905-567-7656");
Object[] arrayEmployees = new Object[4];
arrayEmployees[0] = personLocation;
arrayEmployees[1] = personLocationOverLoaded;
arrayEmployees[2] = personData;
arrayEmployees[3] = personDataOverloaded;
int user = 0;
int menu = 0;
// Get input here, put into variable "user"
switch(user)
{
case 1:
System.out.print("Printing Object Information With Given Values\n\n\t");
arrayEmployees[0]. //Issue
}
}//End Main Method
}//End Class PersonTest
What is Supposed to Happen: I am suppose to be able to reference from my array as shown above (arrayEmployees[0].) and have my methods show up for that particular class.
Object[] arrayEmployees = new Object[4];
arrayEmployees[0] = personLocation;
arrayEmployees[1] = personLocationOverLoaded;
arrayEmployees[2] = personData;
arrayEmployees[3] = personDataOverloaded;
This did exactly what you wanted to do, actually. This is an array that contains objects of both a given type and its superclass.
However, by doing so, you lose some information, as you noticed.
When you create an Object[], you are telling the compiler that "This is an array of Objects". Thus, when you go to retrieve an element of this array, all the compiler knows is that "This array contains Objects". It does not know that the first two elements are PersonLocation instances, and does not know that the last two elements are personData elements. It just knows that the array contains Objects.
This is a fundamental limitation of how collections in Java work in general. Collections in Java have one "overall" type, as in you'll always have a "Collection of Numbers", "array of PersonDatas", "ArrayList of Strings", etc., and not "Collection of Integers and Doubles`" So no matter the actual type of whatever's inside, all the compiler knows that the type of the object you'll get out of the collection is the type of that collection.
For example, say I have List<Number> list = new ArrayList<Number>();. All the compiler knows is that the contents are Numbers. It doesn't know if the first element is an Integer, Double, Long, etc. It's just a Number. And because of that, you can't use a Long-specific method like list.get(0).longValue(), because the compiler can't guarantee that the first element is an Integer. It just knows that list.get(0) returns a Number, and that Numbers don't have a longValue() method.
So how do you solve this?
You have a few options.
Use the instanceof operator to test arrayEmployees[0] for its actual type, then cast as needed and perform desired methods. This is more awkward, but if you must have a single array, you really don't have much of a choice.
Use a separate array for each class, so no information is lost.
Given the assignment you need to do, it seems that multiple arrays aren't an option, as the instructions specify a single array, so you might need to do the test and cast. Here's the general idea:
<variable> instanceof <type>
tests for whether variable is-a <type>. For example:
arrayEmployees[0] instanceof PersonLocation
tests to see if arrayEmployees[0] is a PersonLocation.
This test returns a boolean, so you can use that as the condition for an if statement. Inside that if statement, you can downcast arrayEmployees[0] into a temporary reference:
if (arrayEmployees[0] instanceof PersonLocation) {
PersonLocation temp = (PersonLocation) arrayEmployees[0];
// execute whatever you need on temp
}
Just be warned -- instanceOf will also match subclasses. So both x instanceof Integer and x instanceof Number will both return true if x is declared as Integer x = 1;.
Hopefully that's enough to get you started. Feel free to ask any questions.
I've got a problem.
I'm trying to compare a String and a int but can't seem to get working.
What am I doing wrong?
Getting this from Eclipse:
The type of the expression must be an array type but it resolved to List
int numberOfMoves;
List<String> highscoreLinkedList = new LinkedList<String>();
if (moves < Integer.parseInt(highscoreLinkedList[2])){
highscoreLinkedList[2] = Integer.toString(moves);
highscoreLinkedList[1] = name;
}
This is for a highscore textfile for a game I'm making. The String at index 2 is a number of moves and the int moves is also a number of moves.
You cannot access a list element using highscoreLinkedList[2] - that syntax is reserved for arrays. To access a list you have to use the get() method, i.e. highscoreLinkedList.get(2)
You are trying to treat list as an array, but the only way to access elements of the is through calling get() method. Your code does not compile.
Lists don't work the same way as arrays in Java. To access a certain element, you have to use the get() method, and to get the element, you need to use set(), like so:
// you have highscoreLinkedList[2], it should be:
highscoreLinkedList.get(2);
// you have highscoreLinkedList[2] = ..., it should be:
highscoreLinkedList.set(2, Integer.toString(moves));
You can see all of the methods for LinkedList here.
I've written a function which. Problem is, the parameters I'm sending, is being manipulated in the main program, though it is not my intention. I just want to have the value inside the function, but while operating, the actual value in the main program is also being changed.
How can I prevent this?
Here is my code:
Tiles[][] MoveRight(Tiles[][] tilesArray) {
Tiles[][] tempTilesArray = new Tiles[3][3];
Tiles[][] tempTilesArrayToSend = new Tiles[3][3];
tempTilesArrayToSend = CopyTilesArrays(tilesArray, tempTilesArrayToSend);
ArrayIndex zeroPos = FindZero(tilesArray);
Tiles zeroTile = GetTile(zeroPos, tilesArray);
if (zeroPos.column != 2) {
ArrayIndex otherPos = new ArrayIndex(zeroPos.row,
zeroPos.column + 1);
tempTilesArray = SwapTilesPositions(zeroTile, GetTile(otherPos,
tilesArray), tempTilesArrayToSend);
}
return tempTilesArray;
}
The array I'm sending inside the SwapPositionFunction is actually modifying the tilesArray itself. Though I've made a new instance of tiles array and then sent it.
Without seeing what is done in
CopyTilesArrays (tilesArray, tempTilesArrayToSend);
we can not say much.
Note, that in Java, there is no pass-by-value or pass-by-reference, but a copy of the reference is passed to the methods. This copy of a reference will - in case of objects and Arrays - point to the same, original object, so if you change the underlying/embedded object, the original object is affected, but if you change the reference, the original object is not affected.
IF you want to pass an independent copy of your array, you have to perform a deep ocpy. Maybe that is, what CopyTilesArrays is supposed to do, but without seeing it, we don't know.
Note too, that there are, or better: that there can be several layers of objects, with different reasons to stay on the surface, to go to the core, or to stay somewhere in between.
For example, to make a deep copy from the Array of Array of Tiles, you could do something like this:
public class TilesCopy {
Tiles[][] copyTilesArrays (Tiles[][] from, int outer, int inner) {
Tiles[][] to = new Tiles[outer][inner];
int o = 0;
for (Tiles [] tiles: from) {
Tiles[] fresh = new Tiles [inner];
int i = 0;
for (Tiles t : tiles)
{
fresh[i] = t.deepCopy ();
i++;
}
to [o] = fresh;
o++;
}
return to;
}
}
Note, that in the innermost loop, the elements aren't just referenced with fresh[i] = t;, but with a deep copy, to keep the objects in the original Array unaffected.
You could copy an array of arrays of Tiles in multiple other ways. For example, you could rearrange the outer array. If the Tiles were
[[A][B][C]]
[[D][E][F]]
[[G][H][I]]
you could copy them, and modify the target to be:
[[G][H][I]]
[[D][E][F]]
[[A][B][C]]
with just copying the outer arrays, and rearranging them. And you could copy the inner arrays, to be:
[[C][B][A]]
[[F][E][D]]
[[I][H][G]]
If you now modify the A to a, the original A will be affected too, without a deep copy:
[[C][B][a]]
[[F][E][D]]
[[I][H][G]]
[[a][B][C]]
[[D][E][F]]
[[G][H][I]]
I was wondering, in java, is it possible to in anyway, simulate pass by reference for an array? Yes, I know the language doesn't support it, but is there anyway I can do it. Say, for example, I want to create a method that reverses the order of all the elements in an array. (I know that this code snippet isn't the best example, as there is a better algorithms to do this, but this is a good example of the type of thing I want to do for more complex problems).
Currently, I need to make a class like this:
public static void reverse(Object[] arr) {
Object[] tmpArr = new Object[arr.length];
count = arr.length - 1;
for(Object i : arr)
tmpArr[count--] = i;
// I would like to do arr = tmpArr, but that will only make the shallow
// reference tmpArr, I would like to actually change the pointer they passed in
// Not just the values in the array, so I have to do this:
for(Object i : tmpArr)
arr[count++] = i;
return;
}
Yes, I know that I could just swap the values until I get to the middle, and it would be much more efficient, but for other, more complex purposes, is there anyway that I can manipulate the actual pointer?
Again, thank you.
is there anyway that I can manipulate the actual pointer?
Java does not pass by reference, so you can't directly manipulate the original pointer. As you've found out, Java passes everything by value. You can't pass a reference to an array object, and expect a method to modify the original reference to point to another array object.
You can, of course:
Modify elements of the referred array object (ala java.util.Arrays.sort)
Pass a reference to an object with a settable field (e.g. Throwable has a setStackTrace)
return the new reference instead (ala java.util.Arrays.copyOf)
Well, you can explicitly pass an object that contains a reference. java.util.concurrent.atomic.AtomicReference is ready out of the box, although it does come with volatile semantics that you probably don't want. Some people use single element arrays to returns values from anonymous inner classes (although that doesn't seem a great idea to me).
This method reverses the Array's elements in place. The caller sees the changes. (In Java everything is passed by value, including object references.)
public static void reverse(Object[] arr) {
for ( int i = 0, j = arr.length - 1; i < j; i++, j-- ) {
Object temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
In Java Object reference is passed by value.
So if you looking for something like
function referenceCheck()
{
int[] array = new int[]{10, 20, 30};
reassignArray(&array);
//Now array should contain 1,2,3,4,5
}
function reassignArray(int **array)
{
int *array = new int[] { 1, 2, 3, 4, 5};
}
Then its not possible in Java by any direct means.
If we need to change only the values stored in an array, then we can do it since object reference is passed by value.
You want to pass a reference to the array reference. In that case you just have to either create a class to hold the reference and pass a reference to that class or just pass a 1-element array of the type being passed. Then you'd be passing either an object holding the array or an array whose only element contains the array you want to operate on.