Recently while using arrayList I found a weird issue. I want to keep 2 elements in the arraylist and would like to keep object1 in element 0 and object2 in element1.
I am deciding this in a loop.
When it happens to add the first element its throwing indexOutofBounds. As per java doc as the index is greater than size its doing this.
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
list.add(1,"SECONDITEM"); // throwing due to size is not set
list.add(0,"FIRSTITEM");
int postn=0;
for(String item:list){
System.out.println("Position "+postn+" :"+item);
postn++;
}
}
Then I tried to setup other items as placeholder in 0,1 element and tried to do same
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
list.add(0,"x");
list.add(1,"y");
list.add(1,"SECONDITEM");
list.add(0,"FIRSTITEM");
int postn=0;
for(String item:list){
System.out.println("Position "+postn+" :"+item);
postn++;
}
}
Output:
Position 0 :FIRSTITEM
Position 1 :x
Position 2 :SECONDITEM
Position 3 :y
How to get over this issue. One way I found is to remove the element in the index and add the element. Is there a better option.
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
list.add(0,"x");
list.add(1,"y");
list.remove(1);
list.add(1,"SECONDITEM");
list.remove(0);
list.add(0,"FIRSTITEM");
int postn=0;
for(String item:list){
System.out.println("Position "+postn+" :"+item);
postn++;
}
}
Position 0 :FIRSTITEM
Position 1 :SECONDITEM
.add() method insert the element at the given position and shift the other element accordingly
to overwrite the value at particular index you have to use the .set(position, value)
try the set method ..
list.add(0,"x");
list.add(1,"y");
list.set(1,"SECONDITEM");
list.set(0,"FIRSTITEM");
now it will return the only two values.
When you call in this order:
ArrayList<String> list = new ArrayList<String>();
list.add(1,"SECONDITEM"); // throwing due to size is not set
You are trying to add to position "1", but nothing has been added to the list yet. I believe that is why you get the error. Instead you probably want to use just:
ArrayList<String> list = new ArrayList<String>();
list.add("FIRSTITEM");
Since it's an empty list. You can also use the index, but you'll have to increment each time. Makes sense?
The issue is ... you're trying to use a List in a way it wasn't intended to be used. As you've found out, you can't set or add to an index that is outside the range of the current size.
If you know in advance the size you need and it's a fixed size, using a String[] is the better choice.
If you really want/need a dynamic structure that allows random access sets regardless of the current size, write your own method to fill the list when needed:
public static <T> void fillAndSet(int index, T object, List<T> list)
{
if (index > (list.size() - 1))
{
for (int i = list.size(); i < index; i++)
{
list.add(null);
}
list.add(object);
}
else
{
list.set(index, object);
}
}
Related
I have two fields in my custom class List:
LinkedList<String> breadList;
Iterator<String> iterator.
And I've defined two methods:
showBreadList() - for displaying the contents of the list;
addInOrder() - for inserting a new element into the list (the list should be updated in such a way so that elements are maintained in sorted order).
My code:
public class List {
class LinkedListExample {
private LinkedList<String> breadList = new LinkedList<>(); // <-- Edit from the answer: public to private
Iterator<String> iterator;
public void showBreadList() {
iterator = breadList.iterator();
System.out.println("Values in breadList: ");
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
public void addInOrder(String bread) {
ListIterator<String> stringListIterator = breadList.listIterator();
while(stringListIterator.hasNext()) {
if(stringListIterator.next().compareTo(bread) == 0) {
} else if(stringListIterator.next().compareTo(bread) > 0) {
stringListIterator.previous();
stringListIterator.add(bread);
} else if(stringListIterator.next().compareTo(bread) < 0) {
}
}
stringListIterator.add(bread); // <-- Edit: added
}
}
public static void main(String[] args) {
List list = new List();
List.LinkedListExample lle = list.new LinkedListExample();
lle.addInOrder("Ciabatta");
lle.addInOrder("Wheat Bread");
lle.addInOrder("White Bread");
lle.addInOrder("Sourdough");
lle.addInOrder("Flatbread");
lle.showBreadList();
}
}
The list gets populated in the main() method via addInOrder().
Expected output:
Values in breadList:
Ciabatta
Flatbread
Sourdough
Wheat Bread
White Bread
Actual output:
Value in breadList:
I.e. I'm getting nothing. Can anybody give a hint on what I'm doing wrong?
Seems like the goal of your assignment is to learn how to deal with a ListIterator.
The core thing to understand about the Iterators that their cursor always occupies a position in between the elements of the list (and it might also be positioned before the first element and right after the last element). And that's the position where a new element gets inserted when you invoke ListIterator.add().
Here's a quote from the official tutorial Provided by Oracle:
Intuitively speaking, the cursor is always between two elements — the
one that would be returned by a call to previous and the one that
would be returned by a call to next. The n+1 valid index values
correspond to the n+1 gaps between elements, from the gap before the
first element to the gap after the last one. The following figure
shows the five possible cursor positions in a list containing four
elements.
In the method addInOrder() you've messed around with conditions. If fact, only one condition that would check if the next is lexicographically greater than the given string would be enough. If the next is greater we continue iteration, if not we need to move the iterator the previous position by calling previous() and then break from the loop.
Method add() will be invoked on the iterator after the loop, when iterator is the right position to insert a new element.
That's how you can fix your method:
public void addInOrder(String bread) {
ListIterator<String> iterator = breadList.listIterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (next.compareTo(bread) > 0) { // if the next element is lexicographically greater than `bread`, `bread` has to be inserted before it
iterator.previous(); // moving to the position where the new `bread` should be inserted
break; // breaking out from the loop
}
}
iterator.add(bread); // inserting the new kind of bread
}
Example with the sample data from the question:
LinkedListExample lle = new LinkedListExample();
lle.addInOrder("Ciabatta");
lle.addInOrder("Wheat Bread");
lle.addInOrder("White Bread");
lle.addInOrder("Sourdough");
lle.addInOrder("Flatbread");
lle.showBreadList();
Output:
Ciabatta
Flatbread
Sourdough
Wheat Bread
White Bread
I am trying to use array lists, and I have a row of coordinates. I would like to shift all the coordinates in this row to the front or to the back. I'm not sure if I am on the correct lines here with the code.
List<Coordinate> coordinates = new ArrayList<>();
void addCoordinateToList(Coordinate singleCoordinate) {
coordinates.add(singleCoordinate)
}
void addCoordinateToBackList(ArrayList<> coordinateList) {
for(int i = 0; i < coordinates.size(); i++) {
coordinateList.add(i, coordinateList(i));
}
}
void addCoordinateToFrontList(ArrayList<> coordinateList) {
for(int i = coordinates.size(); i > 0; i--) {
coordinateList.add(i, coordinatesList(i));
}
}
This is not final code, its just writing thoughts out at the moment.
Well, you don't need to use a for loop here.
You could instead utilize the addAll method to achieve what you want:
void addCoordinatesToBack(List<Coordinate> coordinateList) {
coordinates.addAll(coordinateList);
}
void addCoordinatesToFront(List<Coordinate> coordinateList) {
coordinates.addAll(0, coordinateList);
}
addAll has two forms:
addAll(Collection c) adds all elements of the specified Collection at the end of the list;
addAll(int position, Collection c) adds all elements of the specified Collection at the given position. Use position 0 to add them at the beginning of the list.
Also note that I have used List instead of ArrayList with your parameters, as this makes it more flexible.
Note that this is not quite the same as reversing lists.
This functionality is built into the List interface. You can use the following functions for that:
List<String> myList = new ArrayList<>();
//adds to the end of the list
myList.add("reading");
myList.addAll(List.of("the","documentation","first!"));
//adds to the front of the list
myList.add(0,"with");
myList.addAll(0,List.of("It","begins");
Your code
void addCoordinateToBackList(ArrayList<> coordinateList) {
for(int i = 0; i < coordinates.size(); i++) {
coordinateList.add(i, coordinateList.get(i));
}
}
will endlessly add the first element of the original list to beginning of itself. Note that I added the call to List.get(int).
Your last method will throw an ArrayIndexOutOfBounds exception as index i=coordinates.size() is out of bounds. You probably need to change
void addCoordinateToFrontList(ArrayList<> coordinateList) {
for(int i = coordinates.size() - 1; i >= 0; i--) {
coordinateList.add(i, coordinatesList.get(i));
}
}
But this will again add endlessly the last element of the list to itself.
Probably what you want to achieve is:
List<Object> coordinateList = new ArrayList<>();
...
java.util.Collections.reverse(coordinateList);
This will reverse the order of the elements in the list. Note that it will work on the given list and not return anything. This will work only on modifiable lists.
EDIT:
You probably mean to "rotate" the elements, right? There is also the method Collections.rotate(List input, int distance). The documentation:
Rotates the elements in the specified list by the specified distance. After calling this method, the element at index i will be the element previously at index (i - distance) mod list.size(), for all values of i between 0 and list.size()-1, inclusive. (This method has no effect on the size of the list.)
For example, suppose list comprises [t, a, n, k, s]. After invoking Collections.rotate(list, 1) (or Collections.rotate(list, -4)), list will comprise [s, t, a, n, k].
This works in both directions.
I have two lists one is feature and has a placement number based on which i insert data in sorted list e.g if placement number is 5 data will be added in 5th position .i want to add data at 5th postion and to move data which was at 5th position to next index but in my case it just replace data at 5th position not move current data to next position
for (int i = 0; i < featuredList.size(); i++) {
int n = featuredList.get(i).getPlacementNumber().intValue();
if (n < sortedList.size()) {
sortedList.add(n, featuredList.get(i));
} else {
sortedList.add(featuredList.get(i));
}
}
You should use ArrayList, from add(int index, E element)
Inserts the specified element at the specified position in this list. Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices).
Make your sortedList as ArrayList:
List<YourType> sortedList= new ArrayList<YourType>();
See the example http://ideone.com/L6hpsf
String s1 = "s1";
String s2 = "s2";
String s3 = "s3";
List<String> list = new ArrayList<String>();
list.add(s1);
list.add(s3);
list.add(1, s2);
System.out.println(list);
Output: [s1, s2, s3]
Try to use LinkedList to insertion or deletion between list for better performance then ArrayList :
private LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("1");
linkedList.add("2");
linkedList.add("3");
linkedList.add("4");
linkedList.add("5");
// insertion at 3 position
linkedList.add(2,"6");
Another example which may give you some clue and even easy to run :)
import java.util.ArrayList;
public class Alisttest {
public static void main(String[] args) {
ArrayList a = new ArrayList();
a.add("1");
a.add("2");
a.add("3");
a.add("4");
System.out.println("a=> "+a.get(2));
a.add(2, "Pankaj");
System.out.println("a=> "+a.get(2));
System.out.println();
System.out.println("a=> "+a);
}
}
I'm fairly new to Java and I've been trying to solve the following problem unsuccessfully.
Write a Java method that will remove duplicates from a given list.
Assuming:
Method accepts type List
Return type is void
Duplicates are determined using equals()
Main:
Creates an instant of List and loads it with duplicate String values
Invoke removeDuplicates(), pass in this list
Outputs modified list to the console.
I can solve the problem by passing in my list to a new HashSet and copy it back.
But the problem is:
Question is asking me to solve it using equals()...
If the return type is void, how can i output it in the main ?
import java.util.*;
public class Question1 {
public static void main(String[] args) {
String[] words = {"good","better", "best", "best", "first" , "last", "last", "last", "good"};
List<String> list = new ArrayList<String>();
for (String s : words) {
list.add(s);
}
removeDuplicates(list);
}
static void removeDuplicates(List<String> array){
HashSet<String> hs = new HashSet<>();
hs.addAll(array);
array.clear();
array.addAll(hs);
for (String x : array){
System.out.println(x);
}
}
}
EDIT: well, this one works, but as you can see i'm not using equals() and i'm printing out from my static method, not from main.
Also, is there any way I can populate the List faster than using String[] ?
java.util.HashSet uses Object.equals(Object) in its implementation of Set.add(Object) to determine that the element being inserted is unique (as defined by not being equal to another element). HashSet also has the advantage of allowing you to do the de-duping process in O(n) time vs a more naive approach of comparing every element to every other element in O(n^2) time.
The code in main will see the modified list, because the List object is mutable. When a method changes the state of a passed in argument the calling code will see those changes.
removeDuplicates creates a set, then iterates over the input list. If it encounters an element in the input list, that is also in the set, removeDuplicates removes the element from the input list, otherwise it adds the element to the set.
Java is a call-by-reference language (sort of). This means, the method removeDuplicates can modify the List<String> array that it receives and the caller will see that modified list after the call to removeDuplicates returned.
Here's how you would do the same thing without using a Set and just using equals() (also to somewhat answer your "EDIT" question about initializing a List) :
public static void main(String[] args) {
List<String> list = new ArrayList<String>(Arrays.asList(new String[] {
"good", "better", "best", "best", "first", "last", "last", "last",
"good"}));
removeDuplicates(list);
for (String x : list) {
System.out.println(x);
}
}
static void removeDuplicates(List<String> array) {
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
for (int j = 0; j < i; j++) {
// if it has, stop the search and remove it
if (next.equals(array.get(j))) {
array.remove(i);
// decrement i since we just removed the i'th element
i--;
// stop the search
break;
}
}
}
}
That said, using HashSet is a better idea since as has already been pointed out it is more efficient.
If you want the efficiency of HashSet but still preserve the order of the List you could do something like this :
static void removeDuplicates(List<String> array) {
Set<String> set = new HashSet<String>();
for (int i = 0; i < array.size(); i++) {
String next = array.get(i);
// check if this has already appeared before
if (!set.add(next)) {
// if it has then remove it
array.remove(i);
// decrement i since we just removed the i'th element
i--;
}
}
}
The probably easiest way would be to use a Set in the first place, which by definition does not allow duplicates.
For your actual problem, you can do several approaches:
The easy but slow approach: compare each element A with each other element N in the list. If A.equals(N) remove N. Hint: you only need to compare A to each further element, as you have already checked each element before A.
The faster approach: sort the list using the natural comperator. Now you no longer need to compare each element A vs N, but only A vs the next few elements. To be exact: until you find the first element that is not equal to A. In this case you can assume that there is no further duplicate of A (thanks to the sorting) and continue with this next element as A.
The Map approach (fast but takes more memory): for each element put into the list, put the same element into a Map with any Object as value. Now you can just look-up whether or not that element is already in the map, and if it is, it is a duplicate.
The best way would be the 2nd approach as the sorting is very fast, you only need to get each element once, and there is no 2nd list necessary.
Edit: The 2nd approach in code:
static void removeDuplicates(List<String> array) {
if (array.size() <= 1) {
return;
}
Collections.sort(array);
final Iterator<String> it = array.iterator();
String a = it.next(), n;
while (it.hasNext()) {
n = it.next();
if (((a == null) && (n != null))
|| ((a != null) && (a.equals(n) == false))) {
a = n;
} else {
it.remove();
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("good");
list.add("better");
list.add("best");
list.add("best");
list.add("first");
list.add("last");
list.add("last");
list.add("last");
list.add("good");
removeDuplicates(list);
System.out.println(list.toString());
}
public static void removeDuplicates(List<String> list) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
int nextIndex = listIterator.nextIndex();
String nextElement = listIterator.next();
if (list.get(i).equals(nextElement) && i != nextIndex)
listIterator.remove();
}
}
}
}
}
I think it's a fairly simple question, but I can't figure out how to do this properly.
I've got an empty arraylist:
ArrayList<object> list = new ArrayList<object>();
I've got some objects In which I want to add object and each object has to be at a certain position. It is necessary however that they can be added in each possible order. When I try this, it doesn't work and I get an IndexOutOfBoundsException:
list.add(1, object1)
list.add(3, object3)
list.add(2, object2)
What I have tried is filling the ArrayList with null and then doing the above. It works, but I think it's a horrible solution. Is there another way to do this?
You can do it like this:
list.add(1, object1)
list.add(2, object3)
list.add(2, object2)
After you add object2 to position 2, it will move object3 to position 3.
If you want object3 to be at position3 all the time I'd suggest you use a HashMap with position as key and object as a value.
You can use Array of objects and convert it to ArrayList-
Object[] array= new Object[10];
array[0]="1";
array[3]= "3";
array[2]="2";
array[7]="7";
List<Object> list= Arrays.asList(array);
ArrayList will be- [1, null, 2, 3, null, null, null, 7, null, null]
If that's the case then why don't you consider using a regular Array, initialize the capacity and put objects at the index you want.
Object[] list = new Object[10];
list[0] = object1;
list[2] = object3;
list[1] = object2;
You could also override ArrayList to insert nulls between your size and the element you want to add.
import java.util.ArrayList;
public class ArrayListAnySize<E> extends ArrayList<E>{
#Override
public void add(int index, E element){
if(index >= 0 && index <= size()){
super.add(index, element);
return;
}
int insertNulls = index - size();
for(int i = 0; i < insertNulls; i++){
super.add(null);
}
super.add(element);
}
}
Then you can add at any point in the ArrayList. For example, this main method:
public static void main(String[] args){
ArrayListAnySize<String> a = new ArrayListAnySize<>();
a.add("zero");
a.add("one");
a.add("two");
a.add(5,"five");
for(int i = 0; i < a.size(); i++){
System.out.println(i+": "+a.get(i));
}
}
yields this result from the console:
0: zero
1: one
2: two
3: null
4: null
5: five
I draw your attention to the ArrayList.add documentation, which says it throws IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
Check the size() of your list before you call list.add(1, object1)
You need to populate the empty indexes with nulls.
while (arraylist.size() < position)
{
arraylist.add(null);
}
arraylist.add(position, object);
#Maethortje
The problem here is java creates an empty list when you called new ArrayList and
while trying to add an element at specified position you got IndexOutOfBound ,
so the list should have some elements at their position.
Please try following
/*
Add an element to specified index of Java ArrayList Example
This Java Example shows how to add an element at specified index of java
ArrayList object using add method.
*/
import java.util.ArrayList;
public class AddElementToSpecifiedIndexArrayListExample {
public static void main(String[] args) {
//create an ArrayList object
ArrayList arrayList = new ArrayList();
//Add elements to Arraylist
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
/*
To add an element at the specified index of ArrayList use
void add(int index, Object obj) method.
This method inserts the specified element at the specified index in the
ArrayList.
*/
arrayList.add(1,"INSERTED ELEMENT");
/*
Please note that add method DOES NOT overwrites the element previously
at the specified index in the list. It shifts the elements to right side
and increasing the list size by 1.
*/
System.out.println("ArrayList contains...");
//display elements of ArrayList
for(int index=0; index < arrayList.size(); index++)
System.out.println(arrayList.get(index));
}
}
/*
Output would be
ArrayList contains...
1
INSERTED ELEMENT
2
3
*/
How about this little while loop as a solution?
private ArrayList<Object> list = new ArrayList<Object>();
private void addObject(int i, Object object) {
while(list.size() < i) {
list.add(list.size(), null);
}
list.add(i, object);
}
....
addObject(1, object1)
addObject(3, object3)
addObject(2, object2)
This is a possible solution:
list.add(list.size(), new Object());
I think the solution from medopal is what you are looking for.
But just another alternative solution is to use a HashMap and use the key (Integer) to store positions.
This way you won't need to populate it with nulls etc initially, just stick the position and the object in the map as you go along. You can write a couple of lines at the end to convert it to a List if you need it that way.
Bit late but hopefully can still be useful to someone.
2 steps to adding items to a specific position in an ArrayList
add null items to a specific index in an ArrayList
Then set the positions as and when required.
list = new ArrayList();//Initialise the ArrayList
for (Integer i = 0; i < mItems.size(); i++) {
list.add(i, null); //"Add" all positions to null
}
// "Set" Items
list.set(position, SomeObject);
This way you don't have redundant items in the ArrayList i.e. if you were to add items such as,
list = new ArrayList(mItems.size());
list.add(position, SomeObject);
This would not overwrite existing items in the position merely, shifting existing ones to the right by one - so you have an ArrayList with twice as many indicies.
You should set instead of add to replace existing value at index.
list.add(1, object1)
list.add(2, object3)
list.set(2, object2)
List will contain [object1,object2]
Suppose you want to add an item at a position, then the list size must be more than the position.
add(2, item): this syntax means, move the old item at position 2 to next index and add the item at 2nd position.
If there is no item in 2nd position, then this will not work, It'll throw an exception.
That means if you want to add something in position 2,
your list size must be at least (2 + 1) =3, so the items are available at 0,1,2 Position.
in that way it is ensured that the position 2 is accessed safely and there would be no exception.
If you are using the Android flavor of Java, might I suggest using a SparseArray. It's a more memory efficient mapping of integers to objects and easier to iterate over than a Map