Adding elements to ArrayList in java - java

import java.util.ArrayList;
public class ArrayTest {
private static ArrayList<String> list = new ArrayList<String>();
public static void printList () {
System.out.println("Printing the list");
for (int i = 0; i < list.size(); i++)
{
if (list.get(i) != null)
System.out.println(i + " => " + list.get(i));
}
}
public static void add(Integer index, String val) {
while(list.size() <= index)
list.add(null);
list.add(index, val);
}
public static void main(String[] args) {
ArrayTest.add(8, "cover");
ArrayTest.printList();
ArrayTest.add(6, "and");
ArrayTest.printList();
}
}
produces the following output
Printing the list
8 => cover
Printing the list
6 => and
9 => cover
The add(Integer index, String val) function adds an appropriate number of nulls to the list as a check to avoid any IndexOutOfBoundsException exceptions.
Can someone explain why does adding "and" to the list push "cover" a position further in the list ?

Because the add method you used inserts an element at specified index. It doesn't replace the existing element at this position, it add a new, so add the index position from that towards the end.
If you need to replace the value, use the set method.

Because this is the actual specification of the List.add(int index, E element) method:
Inserts the specified element at the specified position in this list
(optional operation). Shifts the element currently at that position
(if any) and any subsequent elements to the right (adds one to their
indices).
As to "why": this is done to avoid overwriting the element on the specified position.

In Java 9, there's an easy way with less number of lines without needing to initialize or add method. Use collection factory methods:
List<String> list = List.of("first", "second", "third");

Related

How to remove every third element from a linked list recursively?

I would like to iterate over a linked list and remove every third element recursively.
If the end of the list is reached, I do the same call on those elements which are left in the linked list. I'm doing that until only one element is left in the linked list.
My solution which does not work as expected:
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
int randomNumber = (int )(Math.random() * 50 + 1);
List<Integer> testList = new LinkedList<Integer>();
for (int i = 1; i <= randomNumber; i++)
{
testList.add(i);
}
}
public void removeElements(List testList)
{
for(int i = 0; i < testList.size();i++){
if(i % 3 == 0){
testList.remove(i);
}
}
if(testList.isEmpty()){
return;
}
removeElements(testList-1);
}
}
If you're doing it recursively, then there's no need to iterate. Simplify the problem down to one iteration and apply it to the current state, and then the rest of the list. There doesn't seem to be a node class, so it has to be done with indexes.
Removing the third element means keeping the current two elements and removing the one after them. We also have to take into account that the list will 'shift' when we remove one, so we don't have to advance forward after removing. The next 'current' will be the same index as the index we removed from.
public void removeElements(List list, int current) {
int removeIndex = current + 2; // remove the third element
if (removeIndex >= list.size()) // if there isn't one, stop
return;
list.remove(removeIndex); // if there is one, remove it
removeElements(list, removeIndex); // continue with the rest of the list
}
To avoid always having to prep the method, you can write a second one that does it for you:
public void removeElements(List list) {
removeElements(list, 0);
}
Ex:
List<Integer> list = new LinkedList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
removeElements(list);
for (int x = 0; x < list.size(); x++)
System.out.println(list.get(x));
// output: 1 2 4 5 7 8 10
Since you updated which nth item you want to remove, this can easily be changed by modifying the value that is added to the current index:
public void removeElements(List list, int current, int n) {
int removeIndex = current + n - 1; // remove the nth element
if (removeIndex >= list.size()) // if there isn't one, stop
return;
list.remove(removeIndex); // if there is one, remove it
removeElements(list, removeIndex, n); // continue with the rest of the list
}
public void removeEverySecond(List list) {
removeElements(list, 0, 2);
}
public void removeEveryThird(List list) {
removeElements(list, 0, 3);
}
// etc.
You are removing items from the list you are iterating over. That makes it vulnerable. The list gets smaller while the iteration gets bigger. This leads to IndexOutOfBounds like errors.
It is probably a better idea to make a copy of the list and remove stuff from the copy based on iteration over the orinal and then return the reduced copy.
remove every third element recursively.
and the code
if(i % 3 == 0){
testList.remove(i);
}
it looks like the code removes first and then every third. Is really what are you expecting? However if you fix it then you will face the issue #GCP has mentioned
package com.company;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> list = new LinkedList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
removeRecursive(list);
System.out.println("The elements that remained in the list are: " + list);
}
public static void removeRecursive(List<Integer> list){
if (list.size() < 3)
return;
for (int i = 2; i < list.size(); i += 2) {
System.out.println("Removing element " + list.remove(i) + " from the list.");
}
removeRecursive(list);
}
}
OK, so what I do here is:
I declare LinkedList of Integers from 1 to 10, I call the recursive method, and printout the final content of the list after recursive method finishes its job.
IN RECURSIVE METHOD:
We take LinkedList of Integers as an argument, our base case is if list.size() is less than 3 (since we need to remove every 3rd element), because if list has less than 3 elements we can't remove the 3rd one (obviously), then we loop from element at index 2 (third element) and remove it, we also increase our i for 2 every time loop ends so we keep deleting every 3rd element until we reach the end of the list. Then we call our recursive method again and we pass our LinkedList with all the remaining elements, eventually when list size is less than 3 our recursive method is done. We then go back to main and print out the elements that remained in the list after everything is finished.
Output for list of 1,2,3,4,5,6,7,8,9,10:
Removing element 3 from the list.
Removing element 6 from the list.
Removing element 9 from the list.
Removing element 4 from the list.
Removing element 8 from the list.
Removing element 5 from the list.
Removing element 7 from the list.
Removing element 10 from the list.
The elements that remained in the list are: [1, 2]

How do I add an object to a linked list in alphabetical order in Java?

I saw similar questions that included an index in the parameters, but my requirements don't allow me to do that. Assume the array is already sorted in alphabetical order.
This is my first time asking a question so sorry if I did something wrong.
public void addElement(Object element){
LinkedListIterator iterator = new LinkedListIterator();
int counter = 1;
int compare = 0;
if(first == null)
iterator.add(element);
else
{
while(iterator.hasNext())
{
compare = getElement(counter).toString().compareToIgnoreCase(element.toString());
//getElement is a method I made to retrieve an element from the linked list
//I have tested it and I know it works. Its parameter is an index
//toString() returns a String of what the element is. example: { Fruit }
//It is in that format with the brackets {}
if(compare != -1)
iterator.add(element);
else
{
iterator.next();
counter++;
}
}
}
}
Based on your question, I don't know exactly what you're using as a comparison value. Is it a string value within the object, the name of the object reference, etc? Assuming that you're inserting an object based on some sort of name variable, this is how you could do it.
Note: I'm sure you can find some sort of existing method/api that does this for you, but I'm assuming you'd like to see how it's done.
For this example, I created a class called AnyObject to iterate and compare. It looks like this:
AnyObject class
public class AnyObject {
private String name;
private int num;
private String color;
public AnyObject(String name, int num, String color) {
this.name = name;
this.num = num;
this.color = color;
}
#Override
public String toString() {
return name;
}
}
Using this simple class, we would modify your code so it looks like this:
AlphaInsertSort Class
import java.util.*;
public class AlphaInsertSort {
public static void main(String[] args) {
ArrayList<AnyObject> myList = new ArrayList<AnyObject>();
myList.add(new AnyObject("alphaObj", 44, "blue"));
myList.add(new AnyObject("betaObj", 7, "orange"));
myList.add(new AnyObject("gammaObj", 12, "red"));
myList.add(new AnyObject("omegaObj", 99, "yellow"));
printList(myList); //helps visualize what's going on
addElement(new AnyObject("charlieObj", 105, "purple"), myList);
printList(myList);
addElement(new AnyObject("aObj", 105, "purple"), myList);
printList(myList);
myList.add(new AnyObject("thetaObj", 0, "green"));
printList(myList);
addElement(new AnyObject("zetaObj", 2, "pink"), myList);
printList(myList);
System.out.println("Finished");
}
public static void addElement(AnyObject element, ArrayList<AnyObject> myList){
ListIterator<AnyObject> iterator = null;
//int counter = 1; don't need this
int compare = 0;
AnyObject current = myList.get(0); //changed name from first to current and will use this for comparison while iterating
iterator = myList.listIterator(); //this should set iterator to start of list. There's no constructor for listIterator
System.out.println("\ncurrent is " + current.toString());
if(current == null)
iterator.add(element);
else
{
while(iterator.hasNext())
{
//compare = getElement(counter).toString().compareToIgnoreCase(element.toString());
compare = current.toString().compareToIgnoreCase(element.toString());
//for display purposes
System.out.println(current.toString() + " compared to " + element.toString() + " is " + current.toString().compareToIgnoreCase(element.toString()));
if(compare > 0) { //want to add element into list if compare is negative. Won't necessarily be -1
iterator.previous(); //will need to move back a spot before adding. Otherwise will always add element after first encountered element that doesn't come before element inserting
iterator.add(element);
break; //make sure to break. No need to continue iterating
}
else
{
current = iterator.next();
//counter++;
}
}
//if element is larger than all existing elements in list
if(!myList.contains(element)) {
iterator.add(element);
}
}
}
public static void printList(ArrayList<AnyObject> myList) {
System.out.println("List contents:");
for(AnyObject element : myList) {
System.out.println(element.toString());
}
System.out.println();
}
}
I removed the counter int because you mentioned in your instructions that you don't have the option to use an index, so there's really no point in including it. It's also worth noting that compareTo and compareToIgnoreCase don't necessarily return -1 and 1. It can return any positive and negative values, so changing your conditions would be smart. Also, compareTo returns a negative number if value that's calling the method is less than the value that it's being compared to, so you want to stop iterating and add the value when compare is negative. Also, since you don't have iterator that's 1 element ahead of the position you're currently at in your list, you need to move the iterator back 1 element when compare returns a negative integer. If you don't, your new element will always be added immediately AFTER the first element that comes after it alphabetically. This is because you can't see the next element immediately after the iterator. Does this make sense?
For instance, if you have a list of 1, 2, 4, 5, and you want to add 3 to it, you would compare 1 to 3, 2 to 3, then 4 to 3. When your iterator reaches 2, it doesn't know what the next value is. Since 3 is larger than 2, it moves on to 4. 4 is less than 3, so add(3) gets called. However, this places 3 after the element it's being compared to (4). Your list would then be 1, 2, 4, 3, 5. The easiest way to fix this is to call iterator.previous(); immediately before iterator.add(3);
Let me know if you'd like further clarification.

Why isn't my program removing "all"?

My problem is, when I output this code, it's not outputting what I want which is to remove the "all". It outputs the same exact thing the first print statement did.
Here's my code:
// RemoveAll
// Spec: To remove the "all"
// ArrayList remove() exercise
import java.util.ArrayList;
public class RemoveAll
{
public static void main(String args[])
{
ArrayList<String> ray;
ray = new ArrayList<String>();
int spot = ray.size() - 1;
ray.add("all");
ray.add("all");
ray.add("fun");
ray.add("dog");
ray.add("bat");
ray.add("cat");
ray.add("all");
ray.add("dog");
ray.add("all");
ray.add("all");
System.out.println(ray);
System.out.println(ray.size());
// add in a loop to remove all occurrences of all
while (spot >= 0)
{
if (ray.get(spot).equalsIgnoreCase("all"))
{
ray.remove(spot);
}
spot = spot - 1;
}
System.out.println("\n" + ray);
System.out.println(ray.size());
}
}
Any ideas?
you are determining size() before filling list
put this after once you have list filled (i.e. after all add())
int spot = ray.size() - 1;
Another way to remove items from the list is to use an Iterator:
for(Iterator<String> i = ray.iterator(); i.hasNext(); ) {
if(i.next().equalsIgnoreCase("all")) {
i.remove();
}
}
That way you don't have to keep track of where you are in the list with respect to removed items.
Two problems. You are setting the size of spot before the array has any values in it so it will have a value of -1 when you get to
while (spot >= 0)
also you are mutating (modifying) the array while you are iterating over it which will cause all sorts of errors. The way you want to do this is using an iterator
Iterator iter = ray.iterator();
while(iter.hasNext()){
String cur = iter.next();
//logic to determin if you need to remove
iter.remove();
}

Ways to iterate over a list in Java

Being somewhat new to the Java language I'm trying to familiarize myself with all the ways (or at least the non-pathological ones) that one might iterate through a list (or perhaps other collections) and the advantages or disadvantages of each.
Given a List<E> list object, I know of the following ways to loop through all elements:
Basic for loop (of course, there're equivalent while / do while loops as well)
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
Note: As #amarseillan pointed out, this form is a poor choice
for iterating over Lists, because the actual implementation of
the get method may not be as efficient as when using an Iterator.
For example, LinkedList implementations must traverse all of
the elements preceding i to get the i-th element.
In the above example there's no way for the List implementation to
"save its place" to make future iterations more efficient.
For an ArrayList it doesn't really matter, because the complexity/cost of get is constant time (O(1)) whereas for a LinkedList is it proportional to the size of the list (O(n)).
For more information about the computational complexity of the built-in Collections implementations, check out this question.
Enhanced for loop (nicely explained in this question)
for (E element : list) {
// 1 - can call methods of element
// ...
}
Iterator
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
ListIterator
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
Functional Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach, Stream.forEach, ...
(A map method from Java 8's Stream API (see #i_am_zero's answer).)
In Java 8 collection classes that implement Iterable (for example, all Lists) now have a forEach method, which can be used instead of the for loop statement demonstrated above. (Here is another question that provides a good comparison.)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
What other ways are there, if any?
(BTW, my interest does not stem at all from a desire to optimize performance; I just want to know what forms are available to me as a developer.)
The three forms of looping are nearly identical. The enhanced for loop:
for (E element : list) {
. . .
}
is, according to the Java Language Specification, identical in effect to the explicit use of an iterator with a traditional for loop. In the third case, you can only modify the list contents by removing the current element and, then, only if you do it through the remove method of the iterator itself. With index-based iteration, you are free to modify the list in any way. However, adding or removing elements that come before the current index risks having your loop skipping elements or processing the same element multiple times; you need to adjust the loop index properly when you make such changes.
In all cases, element is a reference to the actual list element. None of the iteration methods makes a copy of anything in the list. Changes to the internal state of element will always be seen in the internal state of the corresponding element on the list.
Essentially, there are only two ways to iterate over a list: by using an index or by using an iterator. The enhanced for loop is just a syntactic shortcut introduced in Java 5 to avoid the tedium of explicitly defining an iterator. For both styles, you can come up with essentially trivial variations using for, while or do while blocks, but they all boil down to the same thing (or, rather, two things).
EDIT: As #iX3 points out in a comment, you can use a ListIterator to set the current element of a list as you are iterating. You would need to use List#listIterator() instead of List#iterator() to initialize the loop variable (which, obviously, would have to be declared a ListIterator rather than an Iterator).
Example of each kind listed in the question:
ListIterationExample.java
import java.util.*;
public class ListIterationExample {
public static void main(String []args){
List<Integer> numbers = new ArrayList<Integer>();
// populates list with initial values
for (Integer i : Arrays.asList(0,1,2,3,4,5,6,7))
numbers.add(i);
printList(numbers); // 0,1,2,3,4,5,6,7
// replaces each element with twice its value
for (int index=0; index < numbers.size(); index++) {
numbers.set(index, numbers.get(index)*2);
}
printList(numbers); // 0,2,4,6,8,10,12,14
// does nothing because list is not being changed
for (Integer number : numbers) {
number++; // number = new Integer(number+1);
}
printList(numbers); // 0,2,4,6,8,10,12,14
// same as above -- just different syntax
for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
Integer number = iter.next();
number++;
}
printList(numbers); // 0,2,4,6,8,10,12,14
// ListIterator<?> provides an "add" method to insert elements
// between the current element and the cursor
for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
Integer number = iter.next();
iter.add(number+1); // insert a number right before this
}
printList(numbers); // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
// Iterator<?> provides a "remove" method to delete elements
// between the current element and the cursor
for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
Integer number = iter.next();
if (number % 2 == 0) // if number is even
iter.remove(); // remove it from the collection
}
printList(numbers); // 1,3,5,7,9,11,13,15
// ListIterator<?> provides a "set" method to replace elements
for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
Integer number = iter.next();
iter.set(number/2); // divide each element by 2
}
printList(numbers); // 0,1,2,3,4,5,6,7
}
public static void printList(List<Integer> numbers) {
StringBuilder sb = new StringBuilder();
for (Integer number : numbers) {
sb.append(number);
sb.append(",");
}
sb.deleteCharAt(sb.length()-1); // remove trailing comma
System.out.println(sb.toString());
}
}
The basic loop is not recommended as you do not know the implementation of the list.
If that was a LinkedList, each call to
list.get(i)
would be iterating over the list, resulting in N^2 time complexity.
A JDK8-style iteration:
public class IterationDemo {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
list.stream().forEach(elem -> System.out.println("element " + elem));
}
}
In Java 8 we have multiple ways to iterate over collection classes.
Using Iterable forEach
The collections that implement Iterable (for example all lists) now have forEach method. We can use method-reference introduced in Java 8.
Arrays.asList(1,2,3,4).forEach(System.out::println);
Using Streams forEach and forEachOrdered
We can also iterate over a list using Stream as:
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
Arrays.asList(1,2,3,4).stream().forEachOrdered(System.out::println);
We should prefer forEachOrdered over forEach because the behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept.
The advantage with streams is that we can also make use of parallel streams wherever appropriate. If the objective is only to print the items irrespective of the order then we can use parallel stream as:
Arrays.asList(1,2,3,4).parallelStream().forEach(System.out::println);
I don't know what you consider pathological, but let me provide some alternatives you could have not seen before:
List<E> sl= list ;
while( ! sl.empty() ) {
E element= sl.get(0) ;
.....
sl= sl.subList(1,sl.size());
}
Or its recursive version:
void visit(List<E> list) {
if( list.isEmpty() ) return;
E element= list.get(0) ;
....
visit(list.subList(1,list.size()));
}
Also, a recursive version of the classical for(int i=0... :
void visit(List<E> list,int pos) {
if( pos >= list.size() ) return;
E element= list.get(pos) ;
....
visit(list,pos+1);
}
I mention them because you are "somewhat new to Java" and this could be interesting.
You can use forEach starting from Java 8:
List<String> nameList = new ArrayList<>(
Arrays.asList("USA", "USSR", "UK"));
nameList.forEach((v) -> System.out.println(v));
In java 8 you can use List.forEach() method with lambda expression to iterate over a list.
import java.util.ArrayList;
import java.util.List;
public class TestA {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Apple");
list.add("Orange");
list.add("Banana");
list.forEach(
(name) -> {
System.out.println(name);
}
);
}
}
In Java 8 or above, you can iterate a Hashset using forEach() method.
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
HashSet<String> hSet = new HashSet<String>();
// Adding elements into your HashSet usind add()
hSet.add("test1");
hSet.add("test2");
hSet.add("test3");
// Iterating over hash set items
hSet.forEach(x -> System.out.println(x));
// Or you can write shorter:
hSet.forEach(System.out::println);
}
}
For a backward search you should use the following:
for (ListIterator<SomeClass> iterator = list.listIterator(list.size()); iterator.hasPrevious();) {
SomeClass item = iterator.previous();
...
item.remove(); // For instance.
}
If you want to know a position, use iterator.previousIndex(). It also helps to write an inner loop that compares two positions in the list (iterators are not equal).
Right, many alternatives are listed. The easiest and cleanest would be just using the enhanced for statement as below. The Expression is of some type that is iterable.
for ( FormalParameter : Expression ) Statement
For example, to iterate through, List<String> ids, we can simply so,
for (String str : ids) {
// Do something
}
Above you'll find all differents ways to iterate over a LIST.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class test1 {
public static void main(String[] args) {
//******* Exercise 1 : Write a Java program to create a new array list, add some colors (string) and print out the collection.
List<String> colors = new ArrayList<String>();
colors.add("Black");
colors.add("Red");
colors.add("Green");
colors.add("Blue");
System.out.println(colors);
//******* Exercise 2 : Write a Java program to iterate through all elements in a array list.
System.out.println("//******* Exercise 2");
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
// iteration type 1 : using FOR loop
System.out.println("// iteration type 1");
for(Integer nb : list2) {
System.out.print(nb + ", ");
}
System.out.println("\n");
// iteration type 2 : using FOR loop
System.out.println("// iteration type 2");
for(int i=0; i < list2.size(); i++) {
System.out.print(list2.get(i) + ", ");
}System.out.println("\n");
// iteration type 3 : using Do-While loop
System.out.println("// iteration type 3");
int index21 = 0;
do {
System.out.print(list2.get(index21) + ", ");
index21++;
}while(index21<list2.size());
System.out.println("\n");
// iteration type 4 : using While loop
System.out.println("// iteration type 4");
int index22 = 0;
while(index22<list2.size()) {
System.out.print(list2.get(index22) + ", ");
index22++;
}
System.out.println("\n");
// iteration type 5 : using Iterable forEach loop
System.out.println("// iteration type 5");
list2.forEach(elt -> {
System.out.print(elt + ", ");
});
System.out.println("\n");
// iteration type 6 : using Iterator
System.out.println("// iteration type 6");
Iterator<Integer> listIterator = list2.iterator();
while(listIterator.hasNext()) {
System.out.print( listIterator.next() + ", ");
}
System.out.println("\n");
// iteration type 7 : using Iterator (From the beginning)
System.out.println("// iteration type 7");
ListIterator<Integer> listIterator21 = list2.listIterator(list2.size());
while(listIterator21.hasPrevious()) {
System.out.print( listIterator21.previous() + ", ");
}
System.out.println("\n");
// iteration type 8 : using Iterator (From the End)
System.out.println("// iteration type 8");
ListIterator<Integer> listIterator22 = list2.listIterator();
while(listIterator22.hasNext()) {
System.out.print( listIterator22.next() + ", ");
}
System.out.println("\n");
}
}
You could always switch out the first and third examples with a while loop and a little more code. This gives you the advantage of being able to use the do-while:
int i = 0;
do{
E element = list.get(i);
i++;
}
while (i < list.size());
Of course, this kind of thing might cause a NullPointerException if the list.size() returns 0, becuase it always gets executed at least once. This can be fixed by testing if element is null before using its attributes / methods tho. Still, it's a lot simpler and easier to use the for loop

Insert array into correct location of arraylist of int arrays

Overview
I have an arrayList that holds multiple int arrays that have two parameters, key and value. (I know there exists a map library, but for this task I wish to use an arrayList).
Imagine my arrayList has the following arrays:
[3, 99][6, 35][8, 9][20, 4][22, 13][34, 10]
As you can see, they are in order by the index, which is done when I first add them to the arrayList.
My problem
if I want to add an array to this arrayList it would appended to the end of the list, whereas I want to add it to the correct position in the list.
I'm fairly new to arrayLists, and as such was wondering if there exists an elegant solution to this problem that I have not come across.
Current thoughts
Currently, my solution would be to iterate over the arrayList, then for every array temporally store the key (array[0]), I would then iterate over again and add my array in the correct position (where it's key is in-between two other keys).
Your idea of iterating through is correct; however there is no need to perform the iteration twice. Finding the right index and inserting the element can be done in one loop. ArrayList has a method add(int, E) that can insert an element into any position in the list. Try this:
//the value you want to insert
int[] toInsert = {someValue, someOtherValue};
//assume theList is the list you're working with
for(int index = 0; index < theList.size() -1; index ++)
{
int key = theList.get(index)[0];
int nextKey = theList.get(index + 1)[0];
//if we've reached the correct location in the list
if (toInsert[0] > key && toInsert[0] < nextKey)
{
//insert the new element right after the last one that was less than it
theList.add(index + 1,toInsert);
}
}
Note that this method assumes that the list is sorted to begin with. If you want to make that a guarantee, look into some of the other answers describing sorting and Comparators.
It may be more elegant to produce a class to hold your two values and ensure that implements Comparable, as shown below:
public class Foo implements Comparable<Foo> {
private int x; // your left value
private int y; // your right value
// Constructor and setters/getters omitted
public int compareTo(Foo o) {
return Integer.compare(x, o.getX());
}
}
Then add and sort as follows:
List<Foo> listOfFoos = new ArrayList<Foo>;
// ...
listOfFoos.add(new Foo(33,55));
Collections.sort(listOfFoos);
That would be the most readable solution. There may be faster options, but only optimise if you can prove this part is a bottleneck.
First Option
If you want to be able to sort your array you should be storing Comparable Objects.
So, you can create a Class that will hold your two value array and implement the Comparable interface.
If you chose this option, after adding the element all you need to do is to call .sort() on your List.
Second Option
You can define Comparator that you can use for sorting. This would be reusable and would allow you to keep your two dimensional arrays. You will also have to sort after each time you add.
Third Option
You could define your Comparator on the fly as shown in this particular question:
Java Comparator class to sort arrays
you can do the following:
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");
System.out.println("ArrayList contains...");
for(int index=0; index < arrayList.size(); index++)
System.out.println(arrayList.get(index));
}
}
/*
Output would be
ArrayList contains...
1
INSERTED ELEMENT
2
3
*/
There is also a version of add that takes the index at which to add the new item.
int i;
for(i=0; i<arr.size(); i++){
if(arr.get(i)[0] >= newArr[0]){
arr.add(i, newArr);
}
}
if(i == arr.size())
arr.add(i, newArr)
Use a Comparator of int[] along with binarySearch :
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Main
{
public static void main(String[] argv)
{
ArrayList<int[]> list = new ArrayList<int[]>();
list.add(new int[] { 3, 99 });
list.add(new int[] { 6, 35 });
list.add(new int[] { 8, 9 });
list.add(new int[] { 20, 4 });
list.add(new int[] { 22, 13 });
list.add(new int[] { 34, 10 });
Compar compar = new Compar();
addElement(list, new int[] { 15, 100 }, compar);
for(int[] t : list)
{
System.out.println(t[0]+" "+t[1]);
}
}
private static void addElement(ArrayList<int[]> list, int[] elem, Compar compar)
{
int index = Collections.binarySearch(list, elem, compar);
if (index >= 0)
{
list.add(index, elem);
return;
}
list.add(-index - 1, elem);
}
static class Compar implements Comparator<int[]>
{
#Override
public int compare(int[] a, int[] b)
{
return a[0] - b[0];
}
}
}

Categories