ArrayList for loop printing out indexes instead of value - java

I've created a method to read a text file and pull out the name of a contact from each line.
private ArrayList<String> readContacts()
{
File cFile = new File ("Contacts.txt");
BufferedReader buffer = null;
ArrayList <String> contact = new ArrayList<String>();
try
{
buffer = new BufferedReader (new FileReader (cFile));
String text;
String sep;
while ((sep = buffer.readLine()) != null)
{
String [] name = sep.split (",");
text = name[1];
contact.add(text);
}
}
catch (FileNotFoundException e)
{
}
catch (IOException k)
{
}
return contact;
}
I'm trying to populate a JList with each contacts name using the method I've created above using this:
model = new DefaultListModel();
for (int i = 1; i < readContacts().size(); i++)
{
ArrayList <String> name = readContacts();
model.addElement(name);
}
nameList = new JList (model);
add(nameList);
When I run the program, the JList only has the numbers 1-10, instead of each of the contacts names. Is the problem I'm running into here logical or problems with syntax? Any help would be great, thanks!

Don't call readContacts() from within the for loop as that makes no sense. You're creating a new ArrayList multiple times and then adding the entire same ArrayList to your JList, in other words, each element in your JList is an ArrayList (???).
Instead call it in the for loop condition or before the for loop.
Do not have empty catch(...) blocks. Doing this is the programming equivalent of driving your car with your eyes closed -- very dangerous.
For example,
model = new DefaultListModel();
// call readContacts() only *once*
for (String name: readContacts()) {
model.addElement(name);
}

I would say we may create a ArrayList object first, then assign the new readContacts() to this object. After that, read the elements in a loop, if you want, you can print out each elements in the ArrayList to ensure those are you want.

If your program is running, you do not have a syntax problem. Your program is running, but is not giving the expected results. That is a logical problem.
You state:
"the JList only has the numbers 1-10, instead of each of the contacts names."
When I look at your readContacts(), you populate your contact List with name[1]. What is in name[1]? I'm lead to believe that name[1] contains 1 - 10 as you read through your file. What is in name[0], or name[2] or name[3], if they even exist. So my first suggestion will be to try a different index for name since name[1] isn't giving you the right result.
Second, you populated your model with the ArrayList name, instead of using the contents of name. Follow Hovercraft Full Of Eels example to populate your model.

Related

Adding elements to a array list/Pojo

I am having an issue with adding elements to an ArrayList. I created a POJO like my array list.
public class GroupUserMapping {
String group;
ArrayList<String> users;
//setters getters constructor
}
I have a function where I am reading a text file to get Groups which I stored in groups array now for those groups I need to loop through all the records in other text file and get all the users who have this group mapping and according to my condition I am trying to add elements to the Pojo ArrayList like this:
ArrayList<GroupUserMapping> usergroups = new ArrayList< GroupUserMapping >();
ArrayList<String> users = new ArrayList<>();
ArrayList<String> groups = getGroups();// This used for lopping I have certain groups.
Scanner s = null;
String group="";
for(int i= 0;i<groups.size();i++ ){
s = new Scanner(new File(getClass().getClassLoader().getResource(mappingFile).getFile()));
s.useDelimiter("\r\n");
group=groups.get(i);
users.clear();
while (s.hasNext()) {
String aLine = s.next();
String[] value = aLine.split(":");
if(group.equalsIgnoreCase(value[0]))
{
LOGGER.info(group+":"+value[1]);
users.add(value[1]);
}
}
GroupUserMapping groupUserMapping = new GroupUserMapping(group,users);
usergroups.add(groupUserMapping);
s.close();
The issue is when I am reading for Group say G1 I got users u1,u2 and these mapping is correctly stored in usergroups but next loop when I am searching for Group G2 I have users U2,U3. Here in the 2nd loop, it is also updating 1st Group values as well. Ideally my elements should be G1->U1,U2 and G2-> U2,U3 but my code is adding elements like this. G1->U2,U3 G2-> U2,U3. What I am doing wrong here?
The line users.clear(); is causing the issue.
In the first iteration you add users 1 and 2 to that list. Then in the constructor you are passing this list.
GroupUserMapping groupUserMapping = new GroupUserMapping(group,users);
Now in the second iteration, you clear the loop and then add users 2 and 3. Since the first group has the reference to the same list, G1's user list is also cleared and user 2 and 3 are added.
You need to replace the users.clear(); with
users = new ArrayList<String>();
In the above case, the data is unchanged, only the users variable now points to a different location. Hence there won't be any changes to the list of G1.

why is everything getting removed from my arraylist?

I'm trying to answer this question:
Program the method findIngredients. This method takes in a String called
foodInStock, and an ArrayList of Strings called ingredients. The method should return an
ArrayList of ingredients that were not found in foodInStock.
for example if:
foodInStock = “tomatopotatocornturkeycarrotstuffing”
ingredients = {“potato”, “corn”, “salt”, “chicken”, “turkey”}
returns {“salt”, “chicken”}
I tried writing some code but for some reason everything is getting removed when I use the above example on my program. Where did my program go wrong?
Here's my code:
public static ArrayList<String> findIngredients(String foodInStock, ArrayList<String> ingredients){
ArrayList<String> ingredientsNotFound = new ArrayList<String>();
int i = 0;
for (; i < ingredients.size(); i++) {
for (int x = 0; x < foodInStock.length()-(ingredients.get(i).length())+1; x++) {
if (ingredients.get(i) == foodInStock.substring(x, (x + ingredients.get(i).length()))) {
ingredients.remove(i);
i = 0;
break;
}
}
}
ingredients = ingredientsNotFound;
return ingredientsNotFound;
}
I think there are two main things to cover here.
First, the way to build the final result. You are currently removing items from the original input; a better strategy is to add items to a new list (partially because it's simpler to think about and partially because you generally don't want to modify a list while iterating over it).
You also are, probably accidentally, overwriting your list with an empty list at the end.
Second, the way to determine whether or not the ingredient is in the string input. Rather than looping over the whole string and inspecting substrings, you can instead use the indexOf() method to see whether or not the string includes the current item.
public static ArrayList<String> findIngredients(String foodInStock, ArrayList<String> ingredients) {
ArrayList<String> results = new ArrayList<>();
for (String ingredient : ingredients) {
if (foodInStock.indexOf(ingredient) == -1) {
results.add(ingredient);
}
}
return results;
}
Here we initialize a new list for the results. We then loop over every individual ingredient in the input list, and ask whether or not that ingredient is present in the string input. When it is not (indexOf() returns -1), we add it to the results list. At the end, the results contains every ingredient not found.

save multidimensional arrayList

I have a Multidimensional ArrayList, composed of multiple rows of different length. I would like to save the ArrayList as a single tab-delimited file with multiple columns, in which each column corresponds to a specific row of the ArrayList. I have tried to come up with a solution, but the only thing I could think of is to save each ArrayList row in separate files.
The ArrayList is called "array" and it contains several rows of different length. Here is the code:
try {
PrintWriter output = new PrintWriter(new FileWriter("try"));
output.print(array.get(0));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In this case, I can save the first row of the ArrayList as a single file. The other solution I have been thinking about is to loop through the rows, to get as many separate files as the row numbers. However, I would like to get a single file with multiple tab-delimited columns.
Ecxuse me, my old answer was based on a wrong interpretation of your needs.
I made you an example code:
package com.test;
import java.util.ArrayList;
import java.util.List;
public class MulitArrayList {
public static void main(String[] args) {
List<String> innerArrayList1;
List<String> innerArrayList2;
List<String> innerArrayList3;
List<List> outerArrayList;
innerArrayList1 = new ArrayList<String>();
innerArrayList2 = new ArrayList<String>();
innerArrayList3 = new ArrayList<String>();
//comic heros
innerArrayList1.add("superman");
innerArrayList1.add("batman");
innerArrayList1.add("catwoman");
innerArrayList1.add("spiderman");
//historical persons
innerArrayList2.add("Stalin");
innerArrayList2.add("Gandy");
innerArrayList2.add("Lincoln");
innerArrayList2.add("Churchill");
//fast food
innerArrayList3.add("mc donalds");
innerArrayList3.add("burger king");
innerArrayList3.add("subway");
innerArrayList3.add("KFC");
//fill outerArrayList
outerArrayList = new ArrayList<List>();
outerArrayList.add(innerArrayList1);
outerArrayList.add(innerArrayList2);
outerArrayList.add(innerArrayList3);
//print
for(List<String> innerList : outerArrayList) {
for(String s : innerList) {
System.out.print(s + "\t");
}
System.out.println("\n");
}
}
}
The result is:
As you can see, the results are printed with tabs, but the space between them differentiate. You can write it the same way into your file, but this is not the best way to save data. I hope I could help you bit, greetings.

Writing a method with ArrayList of strings as parameters

I am trying to write a method that takes an ArrayList of Strings as a parameter and that places a string of four asterisks in front of every string of length 4.
However, in my code, I am getting an error in the way I constructed my method.
Here is my mark length class
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
And the following is my main class:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
ish.marklength4(words);
}
}
Essentially in this case, it should run so it adds an arraylist with a string of "****" placed before every previous element of the array list because the lengths of the strings are all 4.
BTW
This consists of adding another element
I am not sure where I went wrong. Possibly in my for loop?
I got the following error:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Marklength.marklength4(Marklength.java:7)
at MarklengthTestDrive.main(MarklengthTestDrive.java:18)
Thank you very much. Help is appreciated.
Let's think about this piece of code, and pretend like you don't get that exception:
import java.util.ArrayList;
public class Marklength {
void marklength4(ArrayList <String> themarklength){
for(String n : themarklength){
if(n.length() ==4){
themarklength.add("****");
}
}
System.out.println(themarklength);
}
}
Ok, so what happens if your list just contains item.
You hit the line if(n.length() ==4){, which is true because you are looking at item, so you go execute its block.
Next you hit the line themarklength.add("****");. Your list now has the element **** at the end of it.
The loop continues, and you get the next item in the list, which happens to be the one you just added, ****.
The next line you hit is if(n.length() ==4){. This is true, so you execute its block.
You go to the line themarklength.add("****");, and add **** to the end of the list.
Do we see a bad pattern here? Yes, yes we do.
The Java runtime environment also knows that this is bad, which is why it prevents something called Concurrent Modification. In your case, this means you cannot modify a list while you are iterating over it, which is what that for loop does.
My best guess as to what you are trying to do is something like this:
import java.util.ArrayList;
public class Marklength {
ArrayList<String> marklength4(ArrayList <String> themarklength){
ArrayList<String> markedStrings = new ArrayList<String>(themarklength.size());
for(String n : themarklength){
if(n.length() ==4){
markedStrings.add("****");
}
markedStrings.add(n);
}
System.out.println(themarklength);
return markedStrings;
}
}
And then:
import java.util.ArrayList;
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>();
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
Marklength ish = new Marklength();
words = ish.marklength4(words);
}
}
This...
if(n.length() ==4){
themarklength.add("****");
}
Is simply trying to add "****" to the end of the list. This fails because the Iterator used by the for-each loop won't allow changes to occur to the underlying List while it's been iterated.
You could create a copy of the List first...
List<String> values = new ArrayList<String>(themarklength);
Or convert it to an array of String
String[] values = themarklength.toArray(new String[themarklength.size()]);
And uses these as you iteration points...
for (String value : values) {
Next, you need to be able to insert a new element into the ArrayList at a specific point. To do this, you will need to know the original index of the value you are working with...
if (value.length() == 4) {
int index = themarklength.indexOf(value);
And then add a new value at the required location...
themarklength.add(index, "****");
This will add the "****" at the index point, pushing all the other entries down
Updated
As has, correctly, been pointed out to me, the use of themarklength.indexOf(value) won't take into account the use case where the themarklength list contains two elements of the same value, which would return the wrong index.
I also wasn't focusing on performance as a major requirement for the providing a possible solution.
Updated...
As pointed out by JohnGarnder and AnthonyAccioly, you could use for-loop instead of a for-each which would allow you to dispense with the themarklength.indexOf(value)
This will remove the risk of duplicate values messing up the index location and improve the overall performance, as you don't need to create a second iterator...
// This assumes you're using the ArrayList as the copy...
for (int index = 0; index < themarklength.size(); index++) {
String value = themarklength.get(index);
if (value.length() == 4) {
themarklength.add(index, "****");
index++;
But which you use is up to you...
The problem is that in your method, you didn't modify each string in the arraylist, but only adds 4 stars to the list. So the correct way to do this is, you need to modify each element of the arraylist and replace the old string with the new one:
void marklength4(ArrayList<String> themarklength){
int index = 0;
for(String n : themarklength){
if(n.length() ==4){
n = "****" + n;
}
themarklength.set(index++, n);
}
System.out.println(themarklength);
}
If this is not what you want but you want to add a new string "**" before each element in the arraylist, then you can use listIterator method in the ArrayList to add new additional element before EACH string if the length is 4.
ListIterator<String> it = themarklength.listIterator();
while(it.hasNext()) {
String name = it.next();
if(name.length() == 4) {
it.previous();
it.add("****");
it.next();
}
}
The difference is: ListIterator allows you to modify the list when iterating through it and also allows you to go backward in the list.
I would use a ListIterator instead of a for each, listiterator.add likely do exactly what you want.
public void marklength4(List<String> themarklength){
final ListIterator<String> lit =
themarklength.listIterator(themarklength.size());
boolean shouldInsert = false;
while(lit.hasPrevious()) {
if (shouldInsert) {
lit.add("****");
lit.previous();
shouldInsert = false;
}
final String n = lit.previous();
shouldInsert = (n.length() == 4);
}
if (shouldInsert) {
lit.add("****");
}
}
Working example
Oh I remember this lovely error from the good old days. The problem is that your ArrayList isn't completely populated by the time the array element is to be accessed. Think of it, you create the object and then immediately start looping it. The object hence, has to populate itself with the values as the loop is going to be running.
The simple way to solve this is to pre-populate your ArrayList.
public class MarklengthTestDrive {
public static void main(String[] args){
ArrayList <String> words = new ArrayList<String>() {{
words.add("Kane");
words.add("Cane");
words.add("Fame");
words.add("Dame");
words.add("Lame");
words.add("Same");
}};
}
}
Do tell me if that fixes it. You can also use a static initializer.
make temporary arraylist, modify this list and copy its content at the end to the original list
import java.util.ArrayList;
public class MarkLength {
void marklength4(ArrayList <String> themarklength){
ArrayList<String> temp = new ArrayList<String>();
for(String n : themarklength){
if(n.length() ==4){
temp.add(n);
temp.add("****");
}
}
themarklength.clear();
themarklength.addAll(temp);
System.out.println(themarklength);
}
}

Use of an ArrayList of HashMaps

Could someone tell me what is wrong with the code below? When I run the code below the first line after the try { produces the following error :
"java.lang.IndexOutOfBoundsException: Index: 0, Size: 0"
public static class ASIFFile {
private ArrayList<HashMap<String,String>> data;
private static int currRec = 0; //assign each record a numeric id based on this figure.
// Method for reading ADIFfile
public ArrayList<HashMap<String,String>> ReadASIFfile (File DataFile) {
data = new ArrayList<HashMap<String, String>>(500);
try {
HashMap<String, String> temp = new HashMap<String,String>(10);
data.set(currRec, temp);
(data.get(currRec)).put("recID", Integer.toString(currRec));//give the record a numeric ID
...
You never add anything to your ArrayList. You have an ArrayList that can hold HashMaps, but is currently empty.You have to add a new HashMap to the index you want to use before you use that index.
As Kevin mentioned, you never put anything in your ArrayList. Your code should look something like this...
data = new ArrayList<HashMap<String, String>>(500);
try {
//give the record a numeric ID
data.add(currRec, temp);
In your previous solution, you're calling data.set(currRec, temp); which assumes there is a HashMap element in position currRec of your ArrayList. If you haven't put anything in the ArrayList yet, there will be no element currRec.

Categories

Resources