I am trying to swap 2 objects within an ArrayList. To accomplish this, I am creating a new list where the objects are swapped, then overwrite the old list entirely with the, swapped list. However, I am having trouble adding the objects from the old list to the new list.
The program takes input from a text file, reads the data into objects (circles and rectangles, which are extensions of GeometricObject) and then adds those objects to an ArrayList called objectList.
Here is the code:
public static <E extends Comparable<E>> void swapCells
(ArrayList<E> objectList, int left, int right) {
/* The user may enter the two indices, "left,"
* and, "right," in any order which they desire.
* Because of this it will be necessary to determine
* which is larger or "right" index, and which is
* the smaller or "left" index
*/
int temp;
ArrayList<GeometricObject> swappedList = new ArrayList<GeometricObject>();
if (left > right) {
// Exchanges left and right
temp = left;
left = right;
right = temp;
}
for (int i = 0; i < objectList.size(); i++) {
if (i == left) {
swappedList.add(objectList.get(right));
System.out.println( swappedList.get(i).getArea());
} else {
swappedList.add((E) objectList.get(i));
}
}
} // End of swapCells
I get the following syntax error, and do not know what to do about it.
The method add(GeometricObject) in the type ArrayList<GeometricObject> is not applicable for the arguments (E)
The error is specifically at, swappedList.add(objectList.get(right)); and also wappedList.add((E) objectList.get(i));.
I do not believe this is exactly the answer your looking for, but it may help.
If you typecast with GeomtricObject you will get a functioning code, however, this defeats the purpose of using a generic if your just going to force it into a Geometric Object.
You also need to add else if to get the left object swapped to right position
You may also want to print out the swappedList to confirm that the action has been completed.
for (int i = 0; i < objectList.size(); i++)
{
if (i == left) {
swappedList.add((GeometricObject) objectList.get(right));
}else if (i == right)
swappedList.add((GeometricObject) objectList.get(left));
else {
swappedList.add((GeometricObject) objectList.get(i));
}
}
EDIT 2:
The following will aid you in the operation you were looking for in generics.
You will need to make a temp and cast it to E. You will also need to use the following code as well in its correct arguments and/or form / notation.
E temp
List.set(____ , _____)
List.get(____ )
If your still having trouble with this swap function look at one that is not Generic.
EDIT 3:
You most likely have the same problem as I do, and you also need to sort the Generic. You can use the selectionSort Method below to help you on the assignment. You will need to change the method so that it works for an ArrayList instead of a Array. This means you will need to make use of the suggestions in EDIT 2 to modify the code below. You may also need to use the compareTo Method.
private static void selectionSort(int[] list, int low, int high) {
if (low < high) {
int posMax = high;
int theMax = list[high];
for (int i = 0; i < high; i++) {
if (list[i] > theMax) {
theMax = list[i];
posMax = i;
}// if
}// for
list[posMax] = list[high];
list[high] = theMax;
selectionSort(list, low, high - 1);
}// if
}
You are trying to add E objects to a list of GeometricObject. That’s why you get an error. Your list swappedList should be of type ArrayList<E>, or better: List<E>.
On the other hand, you can modify the type of the function to:
public static void swapCells(ArrayList<GeometricObject> objectList, int left, int right)
Oh, and do something with this list you’ve built. Your current code just discards it.
I first want to thank everyone who contributed to answering this question. I consulted with my teacher on office hours sometime last week. My teacher had me draw out a mental picture of what the problem was before writing the code, then a physical picture on paper and pencil of the process to be used. Finally after writing the code, here is the solution:
public static <E extends Comparable<E>> void swapCells
(ArrayList<E> objectList, int left, int right) {
/*
* Create a temporary generic object so that the left and
* right objects can be swapped without losing any data.
*/
E temp = objectList.get(left);
// Place the right object into the left position
objectList.set(left, objectList.get(right));
/*
* Place the temporary (left) object into the right
* position.
*/
objectList.set(right, temp);
} // End of swapCells
There was really no need to even create a second array list, when one can simply use a temporary object E.
Related
Im working on a game in which multiple "notes" (sprites) are generated.
The notes are created at random. Each of them has a random velocity and are created in a different thread. The Notes class is a child of the sprite class. It has 2 properties and 1 method:
vel - a Velocity2 object holding the x and y component on the
velocity of the note object
pos - a Vector2 object holding the x and y coordinates of the note object.
changepos() - a method that changes the position based on the velocity of the object
(I cannot post the code of that class due to privacy reasons)
I currently have a static class "NoteStack", which can hold up to 64 references to Notes objects.
public class NoteStack {
public Notes[] note_array;
public int stack_len;
public NoteStack(){
note_array = new Notes[64];
stack_len = 0;
}
public void push(Notes n){
if(stack_len<64){
note_array[stack_len] = n;
stack_len++;
Gdx.app.log("push", "pushed");
}
}
public void delete_note(int pos){
if(note_array[pos] != null){
note_array[pos] = null;
for(int i = pos; i<stack_len; i++){
note_array[pos] = note_array[pos+1];
}
note_array[stack_len] = null;
stack_len = stack_len - 1;
}
}
}
Here's the code for my "update" function
public void update(float d, SpriteBatch b){
core.draw(b);
for(int i = 0; i< noteStack.stack_len; i++){
Gdx.app.log("update", "Update function running" + i);
noteStack.note_array[i].changePos(d);
noteStack.note_array[i].draw(b);
// scr_w - screen width , scr_h - screen height
if(noteStack.note_array[i].pos.x > scr_w || noteStack.note_array[i].pos.x < 0 || noteStack.note_array[i].pos.y > scr_h || noteStack.note_array[i].pos.y < 0){
noteStack.delete_note(i);
}
}
}
The issue (as you may see) is that whenever a note object from NoteStack gets removed (i.e. the delete_note method is called), other Notes objects in the array are affected.
Hence my question: What is the best way to reference multiple sprite (note) objects in LibGDX?
Generally speaking in programming, you should never implement own "classic" datastructures, only if it's really necessary and you can't use or extend a collection type, because the standard implementations are well programmed and tested, so those are safer to use.
In your case, I would use libGDX Array. That class has add, get, size methods, and if you really want to, you can extend the Array class to have an update function.
But in short, if you replace public Notes[] note_array; with public Array<Notes> note_array = new Array<>(true, 64); and use get and remove and size for iterating and managing the collection that should work.
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.
I'm building a Java based game in Swing, which is essentially a grid of Jbuttons
I have an Object called Cell, which is a custom JButton with additional parameters for storing objects. The game grid is represented by Cell[][]
I have an arraylist of type Cell[][] to allow me to store the state of the gamegrid after each move. If I want to undo the move, I need to copy the last element of the ArrayList to the game grid to allow it to be displayed on the UI.
My gamegrid is panelHolder and my arraylist is moveHolder.
So far I've tried Collections.copy(panelHolder, moveHolder.get(moveHolder.size())); which will not compile due to the "arguments not being applicable for the type Cell[][]"
I've also tried System.arraycopy(moveHolder.get(moveHolder.size()-1), 0, panelHolder, 0, panelHolder.length);, which throws and out of bounds exception. Initially I thought this was due to the moveHolder.size()-1, but even just as moveHolder.size() it has the same problem.
I've found numerous questions on StackOverflow and others that both show these two ways of doing it, but I can't seem to get it to work. Is there something more obvious I'm missing? Full class method below:
public class UndoClass implements MoveCommand{
public ArrayList<Cell[][]> moveHolder = new ArrayList<Cell[][]>();
public Cell[][] execute(Cell[][] panelHolder) {
if (moveHolder.size() > 0){
Collections.copy(panelHolder, moveHolder.get(moveHolder.size()));
if (moveHolder.size() > 0){
moveHolder.remove(moveHolder.size());
}
}
System.out.println("Move Undone. Undos available:" + moveHolder.size());
return panelHolder;
}
public void addMove(Cell[][] panelHolder){
moveHolder.add(panelHolder);
}
public ArrayList<Cell[][]> getMoves(){
return moveHolder;
}
}
Cell Class
public class Cell extends JButton {
int co_x = 0;
int co_y = 0;
ArrayList<Players> current = new ArrayList <Players>();
}
Just wanted to point our your execute(...) method accepts the Cell[][] both as a parameter and the return argument. That approach is going to force all of your commands to keep copying your input param arrays to the return statement array. Notice if you don't need to keep the two in sync and you just use the return arg, you don't have to worry about copying at all:
Cell[][] lastState = moveHolder.get(moveHolder.size()-1);
moveHolder.remove(moveHolder.size()-1);
return lastState; // Not updating the panelHolder array, just returning
But of course now the input parm and return are out of sync. Instead you might want to encapsulate that state into a single object to make your life easier. Something like this (note that the execute now returns a void):
public ArrayList<GameState> previousStates = new ArrayList<GameState>();
public void execute(GameState currentState) {
if (previousStates .size() > 0) {
GameState lastState = previousStates.get(previousStates.size()-1);
currentState.restoreFrom(lastState);
previousStates .remove(moveHolder.size()-1);
}
}
Good luck on the game!
if (moveHolder.size() > 0) {
for (int i = 0; i < panelHolder.length; i++) {
panelHolder[i] = moveHolder.get(moveHolder.size()-1)[i].clone();
}
moveHolder.remove(moveHolder.size()-1);
}
Try this. You need to make copies of each internal array when copying 2D arrays.
Try a Linked List
LinkedList<Cell[][]> ll = new LinkedList();
ll.removeLast();
panelHolder = ll.clone();
Without the use of any array lists or vectors or any other type of built in java data structure besides arrays, I need to write a method that inserts an animal object in any position and shifts what ever is in the current position and others to the right.
While doing this I must ensure that the collection hasn't already reached its max value.
How do I actually write this method out? My version won't compile do to errors. I cannot figure out this problem. Can someone please help me write this method using my current code and provide an explanation?
private Animal [] objects;
final int MAX_ANIMALS = 100;
public AnimalObject()
{
objects = new AnimalObject[MAX_ANIMALS];
}
public AnimalObject(Animal[]a)
{
objects = a;
}
public void addAnimal(Animal a,int position)
{
Animal [] newAnimal = new Animal[objects.length];
for(int i =0; i < position; i++)
{
newAnimal[i] = objects[i];
}
newAnimal[position] = a;
System.arraycopy(objects, position, newAnimal, position+1, objects.length - position);
for(int i = position+1; i < newData.length; i++)
{
newAnimal[i] = objects[i-1];
}
I will not attempt to fix your incomplete code, I will however offer a possible solution and a piece of advice. Let's start with the advice: do not reinvent the wheel. Unless you are doing this as an excercise, do use an ArrayList. It is made precisely to do that. If it is an excercise, I am not sure if you will gain much by looking for answers on StackOverflow. Best examine ArrayList source code :)
As for a possible solution, here is one - I have tried to mimic what you have pasted above (with minor naming tweaks for readability):
public class AnimalsArray {
final int MAX_ANIMALS = 100;
private Animal[] animals;
public AnimalsArray()
{
this.animals = new Animal[MAX_ANIMALS];
}
public AnimalsArray(Animal[]a)
{
this.animals = a;
}
public void addAnimal(Animal animal, int position) {
Animal[] newAnimals = new Animal[animals.length + 1];
for (int i = 0; i < position; i++) {
newAnimals[i] = animals[i];
}
newAnimals[position] = animal;
System.arraycopy(animals, position, newAnimals, position + 1, animals.length - position);
this.animals = newAnimals;
}
}
You will obviously want to add more methods to that (like retrieval of array's elements I guess). However keep in mind that the above code is HIGHLY inefficient. The array grows each time when an element is added!
When you want to do this right, you should:
Have an initial size of array be larger than required (empty constructor does create a maximum capacity array, but "fixed" version of your code does ignore that and allocate a new array every time an element is added anyway).
When array grows (i.e. you add an element and the array is not large enough to add a new one) you should calculate how much it should grow - an algorithm for that should be designed. When it grows you could use Arrays.copyOf method to allocate a larger array
You can get more ideas on how things should be done by examining ArrayList. Apart from being more efficient it is also generic and this cannot be said about your code (this could be fixed but again - use ArrayList!).
Do I really need to implement it myself?
private void shrinkListTo(ArrayList<Result> list, int newSize) {
for (int i = list.size() - 1; i >= newSize; --i)
list.remove(i);
}
Create a sublist with the range of elements you wish to remove and then call clear on the returned list.
list.subList(23, 45).clear()
This approach is mentioned as an idiom in the documentation for both List and ArrayList.
Here's a fully unit tested code example!
// limit yourHappyList to ten items
int k = yourHappyList.size();
if ( k > 10 )
yourHappyList.subList(10, k).clear();
// sic k, not k-1
alternatively you can use subList method:
public static <T> List<T> shrinkTo(List<T> list, int newSize) {
return list.subList(0, newSize - 1);
}
use ArrayList#removeRange() method:
protected void removeRange(int fromIndex,
int toIndex)
Removes from this list all of the elements whose index is between fromIndex, inclusive, and toIndex, exclusive. Shifts any succeeding elements to the left (reduces their index). This call shortens the list by (toIndex - fromIndex) elements. (If toIndex==fromIndex, this operation has no effect.)
then use ArrayList#trimToSize() method:
Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.
My solution :
public static void shrinkTo(List list, int newSize) {
int size = list.size();
if (newSize >= size) return;
for (int i = newSize; i < size; i++) {
list.remove(list.size() - 1);
}
}
Just use :
shrinkTo(yourList, 6);
There is another consideration. You might want to shy away from using an ArrayList in your method signature, and instead work to the List interface, as it ties you into theArrayList implementation, making changes down the line difficult if you find that, for example, a LinkedList is more suitable to your needs. Preventing this tight coupling does come at a cost.
An alternative approach could look like this:
private void shrinkListTo(List<Result> list, int newSize) {
list.retainAll(list.subList(0, newSize);
}
Unfortunately, the List.retainAll() method is optional for subclasses to implement, so you would need to catch an UnsupportedOperationException, and then do something else.
private void shrinkListTo(List<Result> list, int newSize) {
try {
list.retainAll(list.subList(0, newSize);
} catch (UnspportedOperationException e) {
//perhaps log that your using your catch block's version.
for (int i = list.size() - 1; i >= newSize; --i)
list.remove(i);
}
}
}
That is not as straight forward as your orginal. If you are not tied to the instance of the List that you are passing in, you could just as easily return a new instance by calling subList(int start, int end), and you wouldnt even need to make a method. This would also be a faster implementation, as (in Java 6), you would be getting an instance of an AbstractList.SubList that contains your list, an offset into it and a size. There would be no need for iterating.
If you are interested in the arguments for coding to Interfaces instead of classes, see this favorite article by Allen Holub
I used:
if (list.size() > newSize) {
list = list.subList(0, newSize);
}
This is the util class I use.
public class ArrayUtil {
public static <T>ArrayList<T> reduceSize(ArrayList<T> models, int size){
int k = models.size();
if ( k > size )
models.subList(size, k).clear();
return models;
}
}
Call it in your main class
ArrayUtil.reduceSize(myArrayList, 10);