Why doesn't add method accept my inputs? - java

So far this is my problematic code, assume everything else is made and done:
public GameRecord[] updateHighScoreRecords(GameRecord[] highScoreRecords, String name, int level, int score) {
// write your code after this line
int i = 0;
for (GameRecord gr : highScoreRecords){
if (gr.getScore() >= gr.getScore()){
highScoreRecords.add(i+(gr.getLevel()-level),(Object) new GameRecord(name, level, score)); /*
*adds the new GameRecord in at the (i+gr's level - level)th iteration.
*note it does this because of the assumtion that highScoreRecords is ordered becuase of only using this function
*/
break; //no more need to continue the loop
}
i += 1;
}
return highScoreRecords;
}
as you may have noticed, my code is part of a course, so that is why I'm assuming all other implementations are perfect.

You are passing in a GameRecord[] highScoreRecords array,
but calling a List method add - this does not exist on an Array. You should be getting a compile error.
If you are sure that the array has capacity for insertion then you could do
highScoreRecords[i+(gr.getLevel()-level)] = new GameRecord(name, level, score);
but I guess you would be better off using a List like ArrayList, and keeping your existing code. For this you will to pass a List to the method not an Array.

Java arrays are not dynamic data structures,
highScoreRecords.add(i+(gr.getLevel()-level),
(Object) new GameRecord(name, level, score));
I think you wanted
// Using a List.
GameRecord[] updateHighScoreRecords(List<GameRecord> highScoreRecords,
String name, int level, int score) {
Also, don't cast to Object. That's raw-typeing.

Related

Returning the index of a String parameter in an array

While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else, when I know that the name is within the array, with the array that I'm using for testing. Won't even print the "if - reading" line.
public int find(String name)
{
int index = 0;
for(int i = 0; i < this.shoppingItems.length;i++)
{
if(this.shoppingItems[i].equals(name))
{
System.out.println("If - Reading");
index = i;
}
else
{
index = -1;
}
}
System.out.println(index);
return index;
}
//Main
ShoppingItem[] items = new ShoppingItem[]{new ShoppingItem("Eggs",3.2),new ShoppingItem("Bread",2.8),new ShoppingItem("Bacon",9),new ShoppingItem("Peas",2),new ShoppingItem("Spinach",4),new ShoppingItem("Chocolate",8)};
ShoppingList itemList = new ShoppingList(items);
itemList.find("Bread");
"While I know that this code should work to return the index, for some reason it's skipping the if statement and going straight to the else"
Stop! Java is not wrong; your code is, and it shouldn't work. Your if statement is not being skipped; it's just that the condition is always false, because this.shoppingItems[i] is a ShoppingItem object, and you are comparing it with name, which is a string. A ShoppingItem object is never equal to a string.
Presumably, what you want to test is whether the ShoppingItem object's name is equal to that string. Presumably, your class has a getName method, so you should test:
if(this.shoppingItems[i].getName().equals(name)) {
// ...
}
This is a common kind of programming error, perhaps because it's often acceptable in natural language to say one thing when you mean something closely related; e.g. you might say "I asked the help desk" when really you asked a person at the help desk, you did not ask the desk itself. This is a bit like that; you want the item's name to equal name, not the item itself.
Unless you are compelled to use arrays, you can make things much easier by using lists. They have quite a few useful features.
List<String> items = List.of("bread", "juice", "eggs", "milk");
System.out.println(find("eggs"));
System.out.println(find("butter"));
public int find(String name) {
return items.indexOf(name);
}
Prints
2
-1
That method of the List interface pretty much negates the need to write you own method. I just did it for demonstration purposes.
This example was using a List of Strings and not ShoppingItem class. You could get a List<ShoppingItem> to work by overriding the equals method in your class (something you should get in the habit of anyway).
And here is a taste of how would do it with Stream (java 8+). It presumes list is a simple array of ShoppingItem.
public int find(String name) {
return IntStream.range(0, list.length).filter(
i -> list[i].item.equalsIgnoreCase(name)).findFirst().orElse(-1);
}

Removing null values from array and getting it from the method in Java

I'm trying to remove null values from an array, and returning them to do some other stuff with the new values. However, I'm confused about how to get the updated array.
This is the null removal code.
String[] removeNull(String[] nullArray) {
int nullCounter = 0;
//checking if any is null
for(int i = 0; i < nullArray.length; i++) {
if(nullArray[i]==null) {
nullCounter++;
}
}
String[] noNulls = new String[nullArray.length-nullCounter];
if(nullCounter>0) {
//make a non null array
for(int i = 0, j = 0; i <noNulls.length; i++) {
if(nullArray[i]!=null) {
noNulls[j] = nullArray[i];
j++;
}
}
}
return noNulls;
}
I'm pretty sure that is already correct (Please correct me if I'm wrong). Then, I called it inside a constructor.
public theBoundary(String[] bounds){
removeNull(bounds);
}
After I called removeNull(bounds), will the value of the new array be stored in the array bounds? Or will it be stored in the array noNull? I can't seem to find where the new values are stored.
Thank you, and please tell me if there are mistakes. I've been going around this for half an hour now.
Note: If possible, please don't give me answers that include importing something else. Vanilla Java would be preferred.
removeNull() returns the array noNulls, created inside the method. Currently, in theBoundary(), you simply call removeNull(bounds), but do not assign it to a variable. The newly created null-free array is created, not assigned, and immediately garbage collected.
If you wish to do something with your non-null-containing array (which I assume you do), do this:
public theBoundary(String[] bounds) {
String[] withoutNulls = removeNull(bounds);
doSomething(withoutNulls); // whatever you need here
}
Note, unless you really have to use an array, consider using a List or even a Stream.
List example:
List<String> list = ... // from somewhere else
list.removeIf(s -> s == null);
doSomething(list);
Stream example:
Stream<String> stream = ... //from somewhere else
stream.filter(s -> s != null);
doSomething(stream);
EDIT
Even if you do really need arrays, the following will also work:
String[] noNulls = (String[]) Arrays.stream(inputArray).filter(Objects::nonNull).toArray();
I don't think there is any need to iterate the array twice!
You can instead use a stream on array and filter the indexes without that are NOT NULL.
Also, you can do this without needing to create the removeNull method, and do this directly in your theBoundary method.
Here is how your code will look like:
String[] arrayWithoutNull = Arrays.stream(bounds).filter(Objects::nonNull).toArray(String[]::new)
I hope this solves your problem.
Do you mean this?
public theBoundary(String[] bounds){
String[] cleanedBounds = removeNull(bounds);
}
You are not doing it inplace so you need to assign it back to a new array

text based undo function in java

I'm trying to figure out how to get a undo function for a small maze game. First I worked out a way to do this by checking what the last direction was and just going back in the opposite direction. But this code was getting way too long since I also had to track back possible item pickups or hidden walls etc.
Background info on the code: I use a String[][] to store the maze as this was the easiest. I use an Arraylist<String[][]> to store all the strings.
After each step the player takes I save the String[][] array to the arraylist. When the player say undo I look at the second last String[][] in the arraylist and want to set the String[][] back to this. But the currentPos never seems to get updated. I'm not sure where the problem lies.
if (direction.equals("north")) {
if (currentPos[i - 1][j].equals("---")) {
continue;
} else {
currentPos[i][j] = " ";
currentPos[i - 2][j] = "P";
break;
}
}
if (direction.equals("undo")) {
currentPos = history.get(history.size()-2);
history.remove(history.size()-1);
break;
}
Without understanding the way you are setting history, I've made the assumption from your question that you are simply adding the current map to the history list. If you aren't careful, you will be simply adding the same Object, populating the history with multiply Object references to the current map state. This would have the effect you are observing with the state not changing, because you the history only contains a reference to the most recent map (Not storing any actual history).
To obtain the value from an Object, you typically need to clone the object (invoking the clone() method). However, cloning a 2-dimensional array is somewhat problematic. Invoking the clone() method on a 2-dimensional array "shallow" clones the object, essentially only cloning the first dimension while leaving the second as a reference to the same object (The reason for this is that the first 1-dimension of the array holds a reference to the second 1-dimension). Changing the value on a shallow copied object will change the value of the original and vice-versa, not what you want if you want to keep the Objects distinct.
To create two distinct objects, you will need to perform a "deep" clone, which can be easily implemented in a helper method. The below code illustrates the importance of ensuring you fully clone the object before storing it in the history list.
public static void main (String args[]) throws Exception {
ArrayList<String[][]> list = new ArrayList<>();
String[][] shallowClonedMap = new String[1][1];
String[][] deepClonedMap = new String[1][1];
shallowClonedMap[0][0] = "Old";
deepClonedMap[0][0] = "Old";
list.add(shallowClonedMap.clone());
list.add(deepClone(deepClonedMap));
shallowClonedMap[0][0] = "New";
deepClonedMap[0][0] = "New";
list.add(shallowClonedMap.clone());
list.add(deepClone(deepClonedMap));
for (String[][] item : list) {
System.out.print(item[0][0]);
}
}
public static String[][] deepClone(String[][] arry) {
if (arry == null) {
return null;
}
String[][] clone = new String[arry.length][];
for (int i = 0; i < arry.length; i++) {
clone[i] = arry[i].clone();
}
return clone;
}
The output for executing this code is : NewOldNewNew whereas the "intended" output is "OldOldNewNew". From this you can see the shallowClonedMap was updated to "New" even after being cloned and added to the list.

Android II JAVA Sorting An ArrayList of an object

First of all sorry if my English bad, its not my first language..
I'm working on and android app project, that needed to sort ArrayList of an object..so I made this method to deal with that...
Lets say that I have an object of Restaurant that will contain this data:
private String name;
private float distance ;
And I sort it using the value of the variable distance from lowest to highest:
public void sort(RArrayList<RestaurantData> datas) {
RestaurantData tmp = new RestaurantData();
int swapped;
boolean b = true;
while (b) {
swapped = 0;
for (int i = 0; i < datas.size()-1; i++) {
if (datas.get(i).getDistance() > datas.get(i+1).getDistance()) {
tmp = datas.get(i);
datas.set(i, datas.get(i+1));
datas.set(i+1, tmp);
swapped = 1;
System.err.println("Swapped happening");
}
}
if (swapped == 0) {
System.err.println("Swapped end");
break;
}
}
But when i try the program..the result of an ArrayList is still random, is there any problem with my logic to sort the ArrayList of an object..
Please Help...Thankyou..
Why not use the Collections.sort method?
Here's how you could do it in your project:
public void sort(RArrayList<RestaurantData> datas) {
Collections.sort(datas, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
}
The above solution is a bit "destructive" in the sense that it changes the order of the elements in the original array - datas. If that's fine for you go ahead and use it. Personally I prefer things less destructive and if you have the memory to spare (meaning your array is small) you could consider this solution which copies the array before sorting. It also assumes your RArrayList is an implementation of ArrayList or backed up by it:
public List<RestaurantData> sort(RArrayList<RestaurantData> datas) {
// Create a list with enough capacity for all elements
List<RestaurantData> newList = new RArrayList<RestaurantData>(datas.size());
Collections.copy(newList, datas);
Collections.sort(newList, new Comparator<RestaurantData>() {
#Override
public int compare(RestaurantData lhs, RestaurantData rhs) {
return lhs.getDistance() - rhs.getDistance();
}
});
return newList;
}
Another thing to consider is also to create a single instance of the Comparator used in the method, since this implementation will create one instance per call. Not sure if it's worth it though, because it will also be destroyed quite soon since the scope is local.
Here's the documentation for the Collections api
One last thing, the comparator simply needs to return a value less than 0 if the elements are in the right order, bigger than 0 if they're in the wrong order or 0 if they're the same. Therefore it seems to be that it's enough to simply subtract the distances of each restaurant. However, if this isn't the case, please implement the comparator suiting your needs.

Delete object from array

I've got this constructor in the class Music:
protected String Title;
protected String Autor;
protected String Type;
protected int Code;
public Music (String title, String autor, String type, int code){
this.setTitle(title);
this.setAutor(autor);
this.setType(type);
this.setCode(code);
}
#Override
public String toString(){
return this.Title + " " + this.Autor + " " + this.Type + " " + this.Code;
}
Then, in other class called ManageMusic I create some methods to then use them on the main class. I also define a String array refered to the Music class which I will use in the main class:
private final Music[] musicList;
private int counter;
public ManageMusic(int maxSize) {
musicList= new Music[maxSize];
counter= 0;
public void add(Music m){
musicList[counter] = m;
counter++;
}
Here, I have to create a delete method which would delete a especific object from the musicList and return this list without that object.
This is the way I add music elements to the musicList on the main class:
static ManageMusic musiclist = new ManageMusic(20);
musicList.add(new Music(title, autor, format, code));
My approach for the delete method in the ManageMusic class is to copy this list into a new String[] and then copy it back to the list. But as I'm using an objet from Music instead of from String, I cannot make the copy back because it does not cast the String to the musicList:
public void delete(int code){
String[] newString = new String[musicList.length];
int index_1 = 0;
for (int i=0; i<musicList.length; i++){
if(i != code){
newString[index_1] = musicList[i].toString();
index_1++;
}
}
int index_2 = 0;
for (int i=0; i<newString.length; i++){ //THIS IS WHERE IT SAYS: Cannot convert
// from String to Music
musicList[index_2] = newString[i];
index_2++;
}
}
I have to do something not far from this, because then I've got a method that list elements from the musicList, so I cannot set a return statement for the method.
Why you can do it without an ArrayList
As some people suggested in the comments, you should probably use ArrayLists or similar stuff from the java.util.collection package.
However I assume you want to learn how such things work, so I will not provide you with code (First because I'm too lazy, second to encourage you to learn it yourself) but with some explanation.
edit: First: Your problem is that you copy strings, not references. Instead of trying to use the toString method, try to handle it with the "objects" (i.e. their references) themselves.
Error checking
As you might have noticed your add will cause an IndexOutOfBoundsException if you try to add another entry after your list reached your max_size. You should check for that. You should also check lots of things in the following explanations, I'll provide a few suggestions.
Simple deletion with your exact example
Just use Music[] instead of String[] and copy the reference of the temp Music[] to your musicList.
Better way to handle it: dynamic array structure
So what I suggest is to make use of a dynamic array structure. You will have to copy arrays around a lot, which can be a bit difficult. But basically it's what an ArrayList does.
Constructor
But how to implement that dynamic structure? Let's first start with the initialization, i.e. your constructor. You will not need a parameter for a maximum size (unless you want to restrict your music collection for some reason). Just create an array with size 0. (Of course you can also implement copy constructors and other things, but for the start keep it simple.)
add()
To add more music, you simply create a new array with the size of your current collection + 1, copy all references (this is probably the answer you were looking for. You take the strings, but just take the objects themselves) from the current array to the new array, add the new Music and change the reference of your member variable to your newly created, bigger array (i.e. assigning musicList = tempArray; or something similar). (Error checking: is the object null?)
delete()
For deletion you can do just the same. Create a new temporary array (this time with a reduced size), copy all values over but leave out the one you want to delete. To determine which shall be deleted you can either check for indices or even check the objects for equality. (Error checking: size of temp array should never be smaller than 1, so check if your array is empty - consider to use a method like isEmpty() for that.)
Why should I do this?
Once you got those concepts you will be able to manage your array in whatever way you like. Search through it, delete all elements, copy your music collection to your friend's, etc. etc.
And beyond that?
And after you learned this, go ahead and try the ArrayList - you will figure out it works very much like what you have just written. And now you can be proud that you not only can use ArrayLists, but also know how and why they behave like they do.
Its better to use ArrayList than writing own logic to delete object from existing array. Here is how you can use ArrayList :
{
ArrayList<Music> list = new ArrayList<Music>();
Music m1 = new Music(title, autor, format, code);
list.add(m1);
// similarly you can check whether object is present in ArrayList or not using
if(list.contains(m1)){ // This check whether object is present in ArrayList or not
//Do whatever you want
}
}
ArrayList example:
List<Music> musicList = new ArrayList<Music>();
adding to end of list list:
musicList.add(new Music(...));
adding to specified position in list (later ones all move up one place)
musicList.add(index, new Music(..));
remove from list:
musicList.remove(index);
or
musicList.remove(someMusic);
Size of list:
int size = musicList.size();
Get first music:
Music first = musicList.get(0);
Get last music:
Music last = musicList.get(musicList.size()-1);
Loop:
for (Music : musicList) {
//do stuff
}
do like this
public void delete(int code){
List<Music> list = new ArrayList<Music>(); //creating new empty list
for (Music m:musicList){
if(m.code != code){ // removing condition
list.add(m); // adding music to new list
}
}
musicList = list.toArray(new Music[list.size()]); // assigning back list to musicList
}

Categories