Java Arraylist got java.lang.IndexOutOfBoundsException? - java

I'm a general 3D artist, switched from my career and started to learn programming.
I've got a problem with c106a handout #5.
The code works, but I've still got some error log here.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at UniqueNames.showUnique(UniqueNames.java:23)
at UniqueNames.main(UniqueNames.java:39)
Why does Arraylist, which can stretch its capacity on its own, still get an OutOfBoundsException?
Here's my full code:
import acm.io.*;
import acm.program.ConsoleProgram;
import acm.util.*;
import java.io.*;
import java.util.ArrayList;
import java.lang.*;
public class UniqueNames extends ConsoleProgram{
static ArrayList<String> meString = new ArrayList<String>();
static String input ;
public static void storeUnique(String input){
if (!meString.contains(input))
{
meString.add(input);
}
}
public static void showUnique(ArrayList<String> meString){
System.out.println("Unique name list contains:");
for(int i=0 ;i<= meString.size() ;i++){
System.out.println(meString.get(i));
}
}
public static void main(String[] args){
try{
InputStreamReader stream = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(stream);
while (true){
System.out.println("Enter name:");
String input = br.readLine();
if (input.equals("")) break;
storeUnique(input);
}
{showUnique(meString);}
}
catch(IOException e){
}
}
}

The following lines:
for (int i = 0; i <= meString.size(); i++) {
System.out.println(meString.get(i));
}
should be:
for (int i = 0; i < meString.size(); i++) {
System.out.println(meString.get(i));
}
This is because the index of the list starts from zero.
Index: 4, Size: 4 explains a little more. When you call get(4), an exception occurs because your list only has a size of 4. get(4) would attempt to access the 5th element in the list.
Valid elements you can access would be get(0), get(1), get(2), get(3).

You asked, "Why does Arraylist, which can stretch its capacity by its own still get an OutOfBoundsException ???"
The answer is: an ArrayList only stretches its capacity when:
You add an object to it ( .add(Object o) ).
You add the contents of another collection to it ( .addAll(Collection c) ).
You ensure its size ( .ensureCapacity(int minCapacity) ).
The trouble you're having is that you are trying to access an object in an index of the list that doesn't exist. While an ArrayList will dynamically resize when you change the contents, it won't do it when you are simply trying to access the contents.
That is the difference.
To avoid accessing an index that doesn't exist:
Take Surresh Atta's suggestion: Use i < meString.size() instead of i <= meString.size() because the index starts with 0 instead of 1.
Take Ankit's suggestion and just use the enhanced for loop: for(String str : meString).

Use the above answer, or you can use a foreach loop:
for (String str: meString) {
System.out.println(str);
}

If you are using a 2D ArrayList ,make sure you instantiate every row and every element of the corresponding row using the following code:
for(int i=0;i<n;i++)
{
p.add(new ArrayList<Integer>());
for(int j=0;j<n;j++)
{
p.get(i).add(new Integer(0));
}
}
This creates an ArrayList with i (=n) rows and each row contains an ArrayList with j (=n) number of elements.
If instantiation is not done properly it might result in an IndexOutOfBoundsException

Related

How to add as many elements as i want to an array list by an input?

How to add as many elements as I want to an array list - with only one insert operation?
I want to add 5 Items to a buy list with one input. And then I want to print the 5 items out.
This is what I have done now:
package paket1;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JOptionPane;
public class Class2 {
public static void main(String[] args) {
int i = 0;
while (i != 5) {
String Eingabe = JOptionPane.showInputDialog("Add Einkaufsliste");
ArrayList<String> einkaufsListe = new ArrayList<>();
einkaufsListe.add(Eingabe);
}
}
}
Each time your iteration runs, you are creating a new, empty list, and adding one element to it. But this loop will never finish, because i is never incremented, and will always be 0. The correct code would look like this:
int i = 0;
List<String> einkaufsListe = new ArrayList<>();
while (i <= 5) {
String eingabe = JOptionPane.showInputDialog("Add Einkaufsliste");
einkaufsListe.add(eingabe);
i++;
}
And then you will have to print it as well.
I think it is better to extract this logic into separate method, that retrieves required list. If you want to use ArrayList, do not forget to set initial size.
public static List<String> gibAlleEinkaufe(int insgesamt) {
List<String> einkaufsListe = new ArrayList<>(insgesamt);
for(int i = 0; i < insgesamt; i++)
einkaufsListe.add(JOptionPane.showInputDialog("Add Einkaufsliste"));
return einkaufsListe;
}

Junit Test for a program to remove duplicates in a string array

I am new to Java & Junit testing. My question is, how to fix the error I am getting with the following Junit test code. The Java code returns the desired output when checked with a print statement. Any help is greatly appreciated.
Junit test code
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class RemoveDuplicateTest {
#Test
public void test() {
RemoveDuplicatesStringArray rd = new RemoveDuplicatesStringArray();
String[] strArray = {"ellen","talk","show","ellen","talk","show","ellen","talk"};
rd.removeDups(strArray);
assertEquals(Arrays.asList("show","ellen","talk"),strArray.toString());
}
}
Java code:
import java.util.*;
public class RemoveDuplicatesStringArray {
public List<String> removeDups(String[] str){
List<String> strList = new ArrayList<>();
int count = 0;
for(int i = 0; i < str.length; i++){
for(int j = i+1; j < str.length; j++){
if(str[i].equals(str[j])){
count += 1;
}
}
if(count < 1){
strList.add(str[i]);
}
count = 0;
}
for(int k = 0; k < strList.size(); ){
System.out.println("check "+strList);
System.out.println(strList.getClass());
return(strList);
}
return null;
}
}
To answer you question, your test has a couple of errors:
String[] strArray = {"ellen","talk","show","ellen","talk","show","ellen","talk"};
rd.removeDups(strArray);
removeDups leaves the passed array unchanged and you ignore the result that should be the list containing only the unique elements.
assertEquals(Arrays.asList("show","ellen","talk"),strArray.toString());
Here you compare a list with the string representation of a String array. This will never be evaluated as equal. Even if you change it to
assertEquals(Arrays.asList("show","ellen","talk").tostring(), Arrays.asList(strArray).toString());
you still compare the complete array with all duplicate values with the one with unique values leading to the same result.
I suppose you wanted to do the foll
public void test() {
RemoveDuplicatesStringArray rd = new RemoveDuplicatesStringArray();
String[] strArray = {"ellen","talk","show","ellen","talk","show","ellen","talk"};
List<String> checkList = rd.removeDups(strArray);
assertEquals(Arrays.asList("ellen","talk","show").tostring(),checkList.toString());
}
I changed the order of the values in the list containing the expected values because the values are added to the resulting list in the order they appear in the source list the first time. Otherwise your check will still be negative.
BTW: removeDups is a performance hell. As mentioned in the comments, using HashSet or similar classes are much better because they are
Already available, so you don't need to reinvent the wheel
Much faster because they don't iterate over the whole target list for each input-element

Putting Strings in Lexicographic Order

This is my assignment, and I am not sure how to proceed. The output only prints my first four teachers, and I don't know why it isn't printing my last three teachers as well. Thanks!
Create an ArrayList called teachers. Fill the ArrayList with your teacher’s LAST NAMES ONLY in the order that you see them during the day (Period 1: Jensen, Period 2: Houge, Period 3: …, etc.) You only need to put the teacher’s last name in the ArrayList, so it would print [Jensen, Houge, etc…].) Print the ArrayList using a print method.
Write a method that takes your teachers ArrayList, and from it makes a new ArrayList called ordered, whererin your teacher’s names are now in lexicographic order. Print the resulting ArrayList. (DO NOT CHANGE YOUR ORIGINAL ARRAYLIST, MAKE A NEW ONE!)
import java.util.ArrayList;
public class LexicographicOrdering
{
public static void main (String [] args){
ArrayList<String> teachers = new ArrayList<String>();
teachers.add("Turnbow");
teachers.add("Dyvig");
teachers.add("Williams");
teachers.add("Houge");
teachers.add("Allaire");
teachers.add("Violette");
teachers.add("Dorgan");
System.out.println(teachers);
order(teachers);
}
public static void order(ArrayList<String> teachers ){
ArrayList<String> ordered = new ArrayList<String>();
for(int i = 0; i < teachers.size(); i++){
String str = teachers.get(i);
for(int j = 1; j < teachers.size(); j++){
if(str.compareTo(teachers.get(j)) > 0){
str = teachers.get(j);
}
}
ordered.add(str);
teachers.remove(str);
}
System.out.print(ordered);
}
}
So the issue here is with your static order method. As Karl suggests above, you want to break the method into two separate parts. The first will create an ArrayList named 'ordered' and then fill it with the data contained in the 'teachers' array.
ArrayList<String> ordered = new ArrayList(); //the second <String> is not required
for(int i = 0; i < teachers.size(); i++){
String str = teachers.get(i);
ordered.add(str);
}
The next objective is to sort the array in alphabetical order, which can be achieved using the Collections.sort(ArrayList) method which is contained in the java.util package.
Collections.sort(ordered);
And now you need to print the ArrayList.
System.out.println(ordered);
As this is a homework assignment, I would recommend reading up on the Collections.sort() method, along with an example of it. A quick google search pulled up the following website: http://beginnersbook.com/2013/12/how-to-sort-arraylist-in-java/
Also, I would recommend reading the API for the Collection class. https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-
Edit:
At a quick glance, I would assume the reason that your string is cutting out the last 3 names is due to the fact that you are removing items from the list as you are looking at each position in the list. Essentially, you are looking at every other item in the list because of this.
So I figured it out! I only needed to set the first for loop back to zero. Here is the new code:
import java.util.ArrayList;
public class LexicographicOrdering
{
public static void main (String [] args){
ArrayList<String> teachers = new ArrayList<String>();
teachers.add("Turnbow");
teachers.add("Dyvig");
teachers.add("Williams");
teachers.add("Houge");
teachers.add("Allaire");
teachers.add("Violette");
teachers.add("Dorgan");
System.out.println(teachers);
order(teachers);
}
public static void order(ArrayList<String> teachers ){
ArrayList<String> ordered = new ArrayList<String>();
for(int i = 0; i < teachers.size(); i++){
String str = teachers.get(i);
for(int j = 1; j < teachers.size(); j++){
if(str.compareTo(teachers.get(j)) > 0){
str = teachers.get(j);
}
}
i =- 1;
ordered.add(str);
teachers.remove(str);
}
System.out.print(ordered);
}
}

Removing element from array error

In the following code, if the size of the array is larger than 20, I'm trying to remove anything after 20 from the array. In my loop, I have userinput.remove(20 + i); However, I'm getting that it can't find the symbol remove? I'm not sure why it's doing this if the error.add itself is actually working.
userinput is defined earlier in the code
public static void checknames(String[] userinput){
ArrayList<String> error = new ArrayList<String> ();
if(userinput.length > 20){
for(int i=0; i<userinput.length - 20; i++){
error.add(userinput[20 + i]);
userinput.remove(20 + i);}
JOptionPane.showMessageDialog(null, "You can only enter up to 20
employees. \n The following employees exceed this limit." + error);
}
}
The error is correct - there is no such remove method for arrays. You should either:
Use a List instead, like the ArrayList you have used for error.
Create a new array which is 1 element shorter, and copy over everything except the element you are trying to remove.
You cannot call remove an array. You can't change the size of the array. But you could set that element to null:
userinput[20 + i] = null;
userinput.remove(20 + i);
userinput is array of String[]. There is not method remove(..) available for array.
May be you need to set value to null for indexes greater than 20 (or) create a new String array with only first 20 elements and discard userinput.
Try this:
public static void checknames(String[] userinput) {
List<String> error = new ArrayList<String>();
for(int i=20; i<userinput.length; i++) {
error.add(userinput[i]);
userinput[i] = null;
}
JOptionPane.showMessageDialog(null, "You can only enter up to 20
employees. \n The following employees exceed this limit." + error);
}
Just a few little changes. You should always make ArrayLists like this(with List<...>) on the left-hand side. Also, I got rid of the if statement and slightly changed your loop so you don't need it. And as everyone else mentioned, .remove(...) doesn't work with arrays.
If you insist on keeping the String[], you could delegate the "dirty work" to existing API methods, i.e. Arrays.copyOfRange(Object[] src, int from, int to)
Short, Self Contained, Correct (Compilable), Example:
import java.util.Arrays;
public class R {
public static String[] trimEmployees(String[] employees, int maxSize) {
return Arrays.copyOfRange(employees, 0, maxSize);
}
public static void main(String[] args) {
String[] employees = new String[] { "Jennifer", "Paul", "Tori",
"Zulema", "Donald", "Aleshia", "Melisa", "Angelika", "Elda",
"Elenor", "Kimber", "Eusebia", "Mike", "Karyn", "Marinda",
"Titus", "Miki", "Alise", "Liane", "Suzanne", "Dorothy" };
int max = 20;
System.out.println(String.format("Input employees (len=%d): %s ",
employees.length, Arrays.toString(employees)));
if (employees.length > max) {
employees = trimEmployees(employees, max);
System.out.println(String.format("Trimmed employees (len=%d): %s",
employees.length, Arrays.toString(employees)));
}
}
}
Prints:
Input employees (len=21): [Jennifer, Paul, Tori, Zulema, Donald, Aleshia, Melisa, Angelika, Elda, Elenor, Kimber, Eusebia, Mike, Karyn, Marinda, Titus, Miki, Alise, Liane, Suzanne, Dorothy]
Trimmed employees (len=20): [Jennifer, Paul, Tori, Zulema, Donald, Aleshia, Melisa, Angelika, Elda, Elenor, Kimber, Eusebia, Mike, Karyn, Marinda, Titus, Miki, Alise, Liane, Suzanne]

Limiting an Array

This is my code below, I get an java.lang.IndexOutOfBoundsException & I can't fix it? I am supposed to STOP the error from coming up because I have over 100 names in the file!
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ArrayPractice1 {
public static void main(String[] args) throws FileNotFoundException
{
String[] names = new String[100];
Scanner scan = new Scanner(new File("names.txt"));
int index = 0;
while (scan.hasNext()){
names[index]=(scan.nextLine());
index++;
}
for(int i = 0; i <index -1; i++){
System.out.println(names[i]);
}
}
}
youre not working with an ArrayList of Strings, you're working with a plain array of Strings.
seems like youre getting more than 100 items from scan.hasNext() and so you eventually try to access names[100] and get the exception you describe
instead, you could use this:
ArrayList<String> names = new ArrayList<String>();
and then
while (scan.hasNext()){
names.add(scan.nextLine());
}
and you wont have to worry about knowing the exact size beforehand
If the size of the input is not known at compile time, consider using an ArrayList instead of an array.
Just add the elements to the ArrayList using names.add(scan.nextLine()):
ArrayList<String> names = new ArrayList<String>();
while (scan.hasNext()) {
names.add(scan.nextLine())
}
You are giving 100 as the size of array.If your file have more than 100 lines, definitely it will throw exception
change the condition in your while loop to
while (scan.hasNext() && index < 100)
this will stop the read loop after you fill up the array
Why not making it independent from any upper limit? Use an ArrayList:
ArrayList<String> names = new ArrayList<String>();
Scanner scan = new Scanner(new File("names.txt"));
while (scan.hasNext()){
names.add(scan.nextLine());
}
for(String name : names){
System.out.println(name);
}

Categories