The method public boolean remove(Object o) of List removes an object from list but does not shift the elements following.Just nulls the object value.
IMHO this is an uninintuitive design choice since the size of the list before and after removal remains the same.
Is there an elegant way to get a list with the elements shifted?
Thanks
No, that's not what it does. The element is removed and all indices following it are reduced by one. What makes you think it acts differently?
According to the Java API here it sais that the remove function of List DOES shift
Removes the element at the specified position in this list (optional operation). Shifts any subsequent elements to the left (subtracts one from their indices). Returns the element that was removed from the list.
EDIT:
Main class:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<A> x = new ArrayList<A>();
A one = new A("one");
A two = new A("two");
A three = new A("three");
A four = new A("four");
A five = new A("five");
A six = new A("six");
A seven = new A("seven");
A eight = new A("eight");
A nine = new A("nine");
A ten = new A("ten");
x.add(one);
x.add(two);
x.add(three);
x.add(four);
x.add(five);
x.add(six);
x.add(seven);
x.add(eight);
x.add(nine);
x.add(ten);
for(A item:x){
System.out.println(item.getStr());
}
x.remove(four);
Iterator<A> i = x.iterator();
while(i.hasNext()){
A item = i.next();
System.out.println(item.getStr());
}
}
}
The A Class:
public class A {
private String str;
public A(String x){
this.str = x;
}
public String getStr(){
return this.str;
}
}
works perfectly! no null pointer exception.
This is how it should be done. the first For loop is the alternative syntax for what i did wit the Iterator object. Actually Java automatically translates the first for loop in something that looks like the while loop.
If you look at ArrayList remove implementation, it uses a local method fastRemove(index) as follows:-
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
It does use arraycopy which is a proof that you get whole new list of fresh objects and not the null filled in between. Is this a proof?
The contract for java.util.List implies that calling remove will cause the size() to be decremented. If you're talking specifically about java.util.ArrayList then you might be right about the internal array not shifting its elements, but this is an implementation detail that shouldn't matter to you in 99% of all cases. If it still does matter, then you're trying to optimize for a specific situation and you should probably implement your own List or use something like java.util.LinkedList.
Either your observation is wrong or you are using some other kind of List implementation (and not ArrayList) that doesn't shift the elements to the right of the element being removed. Can you post your code?
If you look at the java.util.ArrayList source code in JDK8, you will see that the remove(Object o) method effectively copies the elements to the right of the element being removed, to the same array starting from the index of the element being removed. Look at the ArrayList source code for more info:
If all you need is an array of the data, then just call toArray().
Related
I have class called Modul and am adding elements of them to my LinkedList. Now I want to write a method where I input an Integer and check if there is an element at that index of the list or if it is empty. if there is a element i will return it and if not i want to return null and an error message.
I have thought of using an if-statement, but ultimately can't think of a method that checks whether or not an element is present. Now I thought of using try-catch but I don't know what kind of error I would need to catch.
import java.util.LinkedList;
public class Modulhandbuch {
private String nameStudienordnung;
private LinkedList<Modul> liste;
public Modulhandbuch(String nameStudienordnung) {
this.nameStudienordnung = nameStudienordnung;
liste = new LinkedList<Modul>();
}
public void einfuegenModul(Modul m) {
liste.add(m);
}
public int anzahlModule() {
return liste.size();
}
public Modul ausgebenModul(int i) {
try {
return liste.get(i);
}catch() //I don't know what error i would need to catch
}
}
You get a null pointer exception if you give the method an integer value that is bigger than the size of the list, because this index does not exist, so you need to check that. The method below correctly handles that case.
public Modul ausgebenModul(int i) {
if (i >= anzahlModule)
return null;
else
return liste.get(i);
}
indexing a linked list is waste of memory it takes O(n) to get to that index in a linkedList if you insist on this then you can add a property to the Node int index and through the constructer Node() increase this and set that instance to that value now there are few little problems to this what happens when you remove a Node at the Start ? yeah big problem the whole list must be reindexed thats makes the process of remove from Start which is O(1) a O(n) operation
you can do a trick to index it or give an illusion of been indexed is just don't do it when you ask for list(6) the iterator counts 6 Nodes Starting with 0 and stop at that Node
I want to rearrange an ArrayList by iterating through it and copying each element to a specific place in a new list.
In this case I want to move an element to the end of the list. For example, if the list is ABCDE and j == B then the new list should be ACDEB.
Here's my code:
private ArrayList<Job> schedule;
private ArrayList<Job> tempSchedule;
...
schedule = input;
tempSchedule = new ArrayList<Job>(schedule.size());
...
private void moveJob(int j) {
for(int i = 0; i < schedule.size(); i++) {
if(i == j) { //move to the end
tempSchedule.set(schedule.size()-1, schedule.get(i));
} else {
if(i > j && i <= schedule.size() -1) { //move one position back
tempSchedule.set(i - 1, schedule.get(i));
} else { //same position
tempSchedule.set(i, schedule.get(i));
}
}
}
schedule = tempSchedule;
u++;
}
Right now I get an IndexOutOfBoundsException: Index: 0, Size: 0 at tempSchedule.set
I guess the problem is with this line
tempSchedule = new ArrayList<Job>(schedule.size());
Also please explain how to make deep copies.
Edit: Thanks for all the answers. I got it to run by simply removing the item and adding it at the end, like suggested.
The reason I wanted to construct a new list is because I might have to do more complex rearrangements at some point.
First, go read the javadoc on ArrayList and collections.
new ArrayList(capacity) doesn't copy, it just allocates a list with that capacity. To copy the list (and it's not a clone, it's a by reference copy, again you need to go back to basics) would be new ArrayList(oldArrayList).
Secondly, Your test has size 0, so there's no objects in it, so get(0) (correctly and as per spec) throws an index out of bounds exception because your list is empty.
Beyond that, neither set nor get will modify the list, so if you had created your copy correctly and it's contents were ABCD and you executed that operation, it's contents would then be ABCB. what you want is.
X = tempSchedule.remove(i) // removes element at I
tempSchedule.add(X) // adds element to end of list
tempSchedule is initialized to be empty:
tempSchedule = new ArrayList<Job>(schedule.size());
You can't use set on an empty ArrayList. It expects the index you are replacing to already have a value.
You get the exception in this line - tempSchedule.set(i, schedule.get(i)); - when i==0.
set calls RangeCheck :
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
As you can see, the index you pass to it must be smaller than the current size of the list.
The problem is that your tempSchedule list is empty. set() overwrites the element at the given position. If your list is empty, it can't do that.
This might be a little confusing since you wrote new ArrayList<Job>(schedule.size()). But the parameter you are passing doesn't set the size but the initial capacity, meaning the initial size of the underlying array, which can be used before it has to be resized.
Reason is when you define arrayList with size of schedule, its an empty list i.e. contains nothing.
So when you try to set an element (which is used to replace the existing element), it compares the index with size of your list and finds that index is 0 and size is 0 as well.
Note just by passing size as constructor, you are not changing the size of arrayList. So in order to avoid this, you need to use:
tempSchedule = new ArrayList<Integer>(schedule);
instead of
tempSchedule = new ArrayList<Integer>(schedule.size());
You have the IndexOutOfBoundsException because you are using schedule.size in your for loop while it's null you have to use tempSchedule.size instead.
And you are comparing i and j while you have to compare tempSchedule.get(i) and j.
You have a syntax fallacy as every other answer stated.
I'm more concerned on your approach.
Can't you just simply do:
private void moveJob(int j) {
Job toMove = tempSchedule.get(j);
tempSchedule.remove(j);
tempSchedule.add(toMove);
}
Or yet more concise:
private void moveJob(int j) {
tempSchedule.add(tempSchedule.remove(j));
}
For example,
class App{
int k;
public App(int k)
{
this.k = k;
}
}
Main Code here:
App one = new App(2);
App Two = new App(3);
PriorityQueue<App> p = new PriorityQueue<>(2,new Comparator<App>() {
#Override
public int compare(App o1, App o2) {
if(o1.k < o2.k) return -1;
return 1;
}
});
p.add(two);
p.add(one);
Obviously, one is at the head of the queue. (p.peek().k is 2)
However, after:
one.k = 9;
two.k = 8;
the one still is at the head of the queue (p.peek.k is 9)!! Priority queue cannot sort automatically when its value has been changed.
Is there a method that can sort the queue when its value is changed?
Hope someone can help.
PriorityQueue and other collections working with comparable elements (e.g. TreeSet) are not meant for mutable objects. They only work if the ordering of the elements does not change (either because you don't change them in that way, or they are immutable and hence cannot be mutated at all).
So what you do, you shouldn't. But if you still do, PriorityQueue does not provide a way to redo the ordering.
Your 2 options:
remove all elements and add them again
create a new PriorityQueue, add all elements and use that
On a side note, your Comparator is not even correct, it should return 0 if 2 values are equal. Try using o1.k - o2.k or Integer.compare(o1.k, o2.k).
I am working on this lab assignment for school and I was wondering if anyone could give me some advice. My instructor wants us to add different number objects up from an array list and display the result. He wants us to do the addition in a non-loop recursive format. I've done a similar problem like this before with just integers, but I cannot seem to get this solution because there is more than one primitive type this time. Here is the Code I have so far:
Main:
import java.math.BigInteger;
import java.util.ArrayList;
public class TestSummation {
public static void main(String[] args) {
ArrayList<Number> aList = new ArrayList<Number>();
aList.add(new Integer(4));
aList.add(new Double(3.423));
aList.add(new Float(99.032));
aList.add(new BigInteger("32432"));
double result = Summation.sum(aList);
System.out.println(result);
}
}
Class that holds the recursive method:
import java.util.ArrayList;
public class Summation {
public static double sum(ArrayList<Number> aList) {
if (aList.size() < 1) {
return 0;
} else {
return sum(aList);
}
}
}
Right now this code throws a StackOverflowException and I was wondering if anyone had advice that would help me. I definitely know I need to add more to it, but I feel I'm on the right track with this current section of code. I'm just hitting a bad roadblock right now. Thanks in advance for any advice!
Recursion always works by cons two different cases:
the base case which is used to end the recursion
the recursive case which is applied on a specific N-th step
By thinking about your problem you can consider as your base case either a list of size 1 or a list of size 0. Let's choose the first for simplicity: the sum of all values of a list of size 1 is the only value that it is contained.
Now let's look for the recursive case: suppose that the list has length N. What we know is that the sum of all elements of a list of N elements is the N-th element added to the sum of a list containing N-1 elements (by removing the N-th element). It's pretty self explicatory as most of recursive implementations.
As you can see the recursive step reduces the size of the list so that the algorithm step-by-step reaches the base case, this is not what is happening to your code.
Since you've done something similar with integers, I gather that the problem is how to deal with the multitude of number class types. Since you want a double result and all Number objects must implement a doubleValue() method, you can use that to build your recursion. To recurse, you need to take the first element's value and add it to the (recurive) summation of the sublist that starts with the second element:
public class Summation {
public static double sum(List<Number> aList) {
final int len = aList.size();
if (len == 0) {
return 0;
}
final double val = aList.get(0).doubleValue();
if (len == 1) {
return val;
}
// help future compilers recognize tail recursion
return val + sum(aList.sublist(1, len));
}
}
Well, without giving it all away, I'll tell you that your code is throwing the exception because you're not modifying the list at all, simply passing it back into your recursive method, which is resulting in an infinite loop. The bit you'll have to add involves modifying the list before passing it into the recursive call (and, of course, doing the actual summation).
I will preface this by saying it is homework. I am just looking for some pointers. I have been racking my brain with this one, and for the life of me i am just not getting it. We are asked to find the minimum element in a list. I know i need a sublist in here, but after that i am not sure. any pointers would be great. thanks.
/** Find the minimum element in a list.
*
* #param t a list of integers
*
* #return the minimum element in the list
*/
public static int min(List<Integer> t) {
if (t.size() == 1){
return t.get(0);
}
else{
List<Integer> u = t.subList(1, t.size());
The point of a recursive algorithm is that everything that must be computed is done through return values or additional parameters. You shouldn't have anything outside the local call of the recursive step.
Since you have to find the minimum element you should take some considerations:
the min element of a list composed by one element is that element
the min element of a generic list is the minimum between the first element and the minimum of the remaining list
By taking these into consideration it should be easy to implement. Especially because recursive algorithms have the convenience of being really similar to their algorithmic description.
You need to find the relationship between the function min applied to a list and the function min applied to a sublist.
min([a b c d e ...]) = f(a, min([b c d e ...]))
Now you just need to find the function f. Once you have the relationship, then to implement it is easy. Good luck.
In the most general sense, recursion is a concept based on breaking down work, and then delegating the smaller chunk of work to a copy of yourself. For recursion to work, you need three main things:
The breakdown of work. How are you going to make each step "simpler"?
The recursive call. At some point your function must call itself, but with less "work".
The base case. What is a (usually trivial) end case that will stop the recursion process?
In your case, you're trying to create a function min that operates on a list. You're correct in thinking that you could somehow reduce (breakdown) your work by making the list one smaller each time (sublist out the first element). As others have mentioned, the idea would be to check the first element (which you just pulled off) against the "rest of the list". Well here's where the leap of faith comes in. At this point, you can "assume" that your min function will work on the sublist, and just make a function call on the sublist (the recursive call). Now you have to make sure all your calls will return (i.e. make sure it will not recurse forever). That's where your base case comes in. If your list is of size 1, the only element is the smallest of the list. No need to call min again, just return (that part you already have in your original post).
/**
* The function computes the minimum item of m (-1 if m is empty).
* #param m: The MyList we want to compute its minimum item.
* #return: The minimum item of MyList
*/
public int minimum(MyList<Integer> m){
int res = 0;
int e0 = 0;
int e1 = 0;
// Scenarios Identification
int scenario = 0;
// Type 1. MyLyst is empty
if(m.length() == 0) {
scenario = 1;
}else {
// Type 2. MyLyst is not empty
scenario = 2;
}
// Scenario Implementation
switch(scenario) {
// If MyLyst is empty
case 1:
res = -1;
break;
// If there is 1 or more elements
case 2:
//1. Get and store first element of array
e0 = m.getElement(0);
//2. We remove the first element from MyList we just checked
m.removeElement(0);
//3. We recursively solve the smaller problem
e1 = minimum(m);
//4. Compare and store results
if(e0 < e1) {
res = e0;
}
else {
res = e1;
}
//5. Return removed element back to the array
m.addElement(0, e0);
break;
}
//6. Return result
return res;
}
There you go, Try this out in the method:
public static Integer minimum(List<Integer> t) {
int minInt;
if (t.size() == 1) {
return t.get(0);
} else {
int first = t.get(0);
List<Integer> u = t.subList(1, t.size());
minInt = Math.min(first, u.get(0));
minInt = IntegerList.minimum(u);
}
return minInt;
}
Hopefully this solves your issue.