Iterator seems to be losing data java - java

I've got a method that returns a list of hashmaps (the data comes from a ResultSet).
While trying to use an iterator to loop through the data and convert it to a String array, I was finding that the code was not working - It seemed to be losing half of my array data while doing the loop.
When swapping it to use a for loop rather than an iterator, the data was not lost. I tried using both an Iterator() and ListIterator() to no avail
Here is my original code (that wasn't working):
public String[][] getLayoutEdges() throws SQLException {
ArrayList<String[]> returnArray = new ArrayList<>();
List<HashMap> layoutEdges = db.getLayoutEdgesFromDatabase();
ListIterator<HashMap> edgesIterator = layoutEdges.listIterator();
while(edgesIterator.hasNext()) {
ArrayList<String> tmpList = new ArrayList<>();
tmpList.add(edgesIterator.next().get("fromnode").toString());
tmpList.add(edgesIterator.next().get("tonode").toString());
tmpList.add(edgesIterator.next().get("distance").toString());
String[] tmpStr = new String[tmpList.size()];
returnArray.add(tmpList.toArray(tmpStr));
}
String[][] rtn = new String[returnArray.size()][returnArray.size()];
return returnArray.toArray(rtn);
}
Here is the code that does work:
public String[][] getLayoutEdges() throws SQLException {
ArrayList<String[]> returnArray = new ArrayList<>();
List<HashMap> layoutEdges = db.getLayoutEdgesFromDatabase();
for(HashMap tmp : layoutEdges) {
ArrayList<String> tmpList = new ArrayList<>();
tmpList.add(tmp.get("fromnode").toString());
tmpList.add(tmp.get("tonode").toString());
tmpList.add(tmp.get("distance").toString());
String[] tmpStr = new String[tmpList.size()];
returnArray.add(tmpList.toArray(tmpStr));
}
String[][] rtn = new String[returnArray.size()][returnArray.size()];
return returnArray.toArray(rtn);
}
Can anybody tell me why the iterator wasn't working? I'm okay with using a for loop, i just can't for the life of me work out why the original iterator code I wrote wasn't keeping all my data. Wondering if there's a step i'm missing or whether I was trying to use the wrong solution.

You're calling edgesIterator.next() three times for each iteration of the loop in your first snippet, which I'm pretty sure you don't want to do. Just don't do that:
while (edgesIterator.hasNext()) {
HashMap tmp = edgesIterator.next();
tmpList.add(tmp.get("fromnode").toString());
tmpList.add(tmp.get("tonode").toString());
tmpList.add(tmp.get("distance").toString());
String[] tmpStr = new String[tmpList.size()];
returnArray.add(tmpList.toArray(tmpStr));
}
As an aside, if you could avoid using raw types in your API, it would generally be cleaner - I'm talking about the use of HashMap here.
I would also generally favour the second version of your code anyway - unless you need to use the iterator explicitly for some reason, let the syntactic sugar of the enhanced for loop do it for you automatically.

Because of these lines :
tmpList.add(edgesIterator.next().get("fromnode").toString());
tmpList.add(edgesIterator.next().get("tonode").toString());
tmpList.add(edgesIterator.next().get("distance").toString());
The moment you are calling edgesIterator.next() its moving the cursor to the next element.

Related

How to map each item from several lists into the object in Java without using for loops

I have 3 lists which describe user: status, name, email. I need to put each elements from each list into an object(e.g get each first element from each list and put them into UserItem and add object to list, so it describes my 1st user and so on). I use following solution, but I want to know is there any design pattern to solve this in more efficient way? I want to avoid classic for loops(ive tried to find solution using stream api, but vainly).
public List<UserItem> mapToObject(final List<String> statusList, final List<String> nameList, final List<String> emailList) {
for (int i = 0; i < emailList.size(); i++) {
var item = new UserItem();
item.setStatus(statusList.get(i));
item.setName(nameList.get(i));
item.setEmail(emailList.get(i));
setItem(item);
}
return getItems();
}
For making objects using data gathered from lists or any kind of array type data objects, you need looping, so you should use for loop, while loop or as in comments the forEach loop.
If you need some design pattern answer I'll go with using an iterator for each list.
public List<UserItem> mapToObject(final List<String> statusList, final List<String> nameList, final List<String> emailList) {
List<UserItem> users = new ArrayList<>();
Iterator statusIt = statusList.iterator();
Iterator nameIt = nameList.iterator();
Iterator emailIt = emailList.iterator();
while (statusIt.hasNext() && nameIt.hasNext() && emailIt.hasNext()) {
UserItem item = new UserItem();
item.setStatus((String)statusIt.next());
item.setName((String)nameIt.next());
item.setEmail((String)emailIt.next());
users.add(item);
}
return users;
}

Deleting specific object from ArrayList using for-loop

I am trying to delete one object from an ArrayList, but after iterating through the list with the for loop i'm stuck at what to do next. nameInput is a lowercase string from the user.
If i run this it prints the object from arr list equal to the input from nameInput. But I cannot understand how to go from printing that object to deleting it?
I'm sure this is a stupid question but the 50+ answers i have read and tried all seem to fail me (or more likely I fail to understand them). I have tried the list.remove and removeIf.
private ArrayList<Arr> arr = new ArrayList<>();
private void removeItem() {
for (Object arr : arr) {
if (((Arr) arr).getName().equals(nameInput())) {
System.out.println(arr);
break;
} else {
System.out.println("Error");
}
}
}
Using for loop
List<Arr> arr = new ArrayList<>();
for (Arr item : arr) {
if (item.getName().equals(nameInput())) {
arr.remove(item);
break;
}
}
If not call break after remove element, you get ConcurrentElementException
Note from #Aomine: you have to implement correct Arr.equals() method.
Using Iterator
List<Arr> arr = new ArrayList<>();
Iterator<Arr> it = arr.iterator();
while (it.hasNext()) {
Arr items = it.next();
if (item.getName().equals(nameInput())) {
it.remove();
break; // you can continue iterating and remove another item
}
}
Using Streams
List<Arr> arr = new ArrayList<>();
arr.removeIf(item -> item.getName().equals(nameInput()));
Remove all items that match given condition
This is not good to remove element from ArrayList. In case you know that you have to remove element from the middle of the List, do use LinkedList.
You are trying to remove an item while you are traversing/iterating the list in the for loop. You cannot remove an item from the list iterating it in a for loop. Use an Iterator instead and invoke arr.remove().
If you use Java 8 you could do
private void removeItem() {
arr.removeIf(t -> t.getName().equals(nameInput));
}
Note that this will remove all objects with name equal to nameInput
Also you should change your declaration of arr to
List<Arr> arr = new ArrayList<>();
A couple of things here...
The loop variable receiver type should ideally be Arr instead of Object as the list contains Arr objects. This also means you no longer need the cast you're performing.
You could remove the item via remove(Object o) but this requires overriding equals and hashcode based on name only. Another option is via an iterator but this would mean changing your code completely. Thus, to keep it as close to your code as possible you can use a for loop; get the index which the object is located and then remove.
Thus, you can do:
for(int i = 0; i < arr.size(); i++){
if (arr.get(i).getName().equals(nameInput)) {
Arr obj = arr.remove(i); // remove the item by index
System.out.println(obj); // print the object
break; // terminate the loop iteration
}
}

comparing 2 ArrayList in Java

I got 2 ArrayList
List fileArray = new ArrayList();
List fileTxt = new ArrayList();
List<String> newDoc = new ArrayList<String>();
while((fileName = fileRead.readLine()) !=null){
fileArray.add(fileName);
}
fileRead.close();
while((txtName = txtRead.readLine()) !=null){
fileTxt.add(txtName);
}
txtRead.close();
I want to compare fileArray data with fileTxt data, but don't know how to do that, because to I'm thinking to compare I need to get the data first. And to do that I need to looping the array and using the .get like
for(int a=0;a<fileTxt.size();a++){
System.out.println(fileTxt.get(a));
}
I know this is wrong, but anyone can help me.
note: I want to use something like contains method but can't because the data is 5 million rows. (not equals method)
Updated: I want to find a word in fileTxt that appeared in the fileArray. (so basically its like contains)
To compare 2 values in your 2 arraylists, you do this:
if(fileArray.get(index).equals(fileTxt.get(index)))
There is a wondefull function.
System.out.println(array1.equals(array2));
Then, you might want to check your answer by hands:
ArrayList like1 = new ArrayList();
ArrayList like2 = new ArrayList();
...
boolean flag = true;
if (!Math.min(like1.size(), like2.size()) == Math.max(like1.size(), like2.size()))
{
flag = false;
}
for (int i = 0; i < Math.min(like1.size(), like2.size()); i++) {
if (!like1.get(i).equals(like2.get(i))) {
flag = false;
break;
}
}
You can do this using the removeAll() method.
fileArray.removeAll(fileTxt);
fileTxt.removeAll(fileArray);
If one of them still have data, this means that the two List where different.
But storing 5 millions data in a Java list is not something I will advise you. Perhaps you should think about something else.

Performance related for conversion from String array to ArrayList

I am converting an empty String array (which i may get from middleware) to List .
For Conversion process i used Arrays.asList (Please see below code ) which is throwing an java.lang.UnsupportedOperationException .
public class Ramddd {
public static void main(String args[]) {
String[] words = null;
if (words == null) {
words = new String[0];
}
List<String> newWatchlist = Arrays.asList(words);
List<String> other = new ArrayList<String>();
other.add("ddd");
newWatchlist.addAll(other);
}
}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(Unknown Source)
at java.util.AbstractList.add(Unknown Source)
at java.util.AbstractCollection.addAll(Unknown Source)
at Ramddd.main(Ramddd.java:18)
I dont get this Error if i use
List<String> mylist = new ArrayList<String>();
for (int i = 0; i < words.length; i++) {
mylist.add(words[i]);
}
This forms an proper List and any operations like addALL , removeALL seems good , but dont want to go to this for loop approach , as it may result in performance .
Please let me know what is the best and safe approach for converting a String array to ArrayList .
How about the following:
public class Ramddd {
public static void main(String args[]) {
String[] words = getWords();
if (words == null) {
words = new String[0];
}
List<String> other = new ArrayList<String>(Arrays.asList(words));
other.add("ddd");
}
}
In terms of performance, I don't this this is something to worry about, unless you have a really gigantic array of Strings.
The method java.util.Arrays.asList(T...) returns a fixed-size list backed by the specified array. This implementation of List for this method (java.util.Arrays.ArrayList) don't have support for these methods. See the documentation for the java.util.AbstractList.
If you know the total size of your list of words, you can init the capacitity for ArrayList, adding n elements requires O(n) time. If you don't know the final size, use LinkedList.
See more in List Implementations (The Java Tutorials > Collections > Implementations).

How to remove multiple elements in Vector in Java?

I read from .txt file all of the ids and insert these ids into Vector.
String pathSelectedfile = fileChooser.getSelectedFile().getAbsolutePath();
File selectedFile = new File(pathSelectedfile);
Scanner readFile = new Scanner(selectedFile);
Vector ids=new Vector();
while (readFile.hasNextLine()) {
String id= readFile.nextLine();
ids.addElement(id);
}
then I want to remove multiple ids in Vector.i can do that by for loop
but information is too big.tnx a lot
To remove multiple values
Vector vector = new Vector();
vector.add("value1");
vector.add("value2");
vector.add("value3");
vector.add("value4");
System.out.println("Size : "+vector.size());
// to remove single value
vector.remove("value1");
System.out.println("Size : "+vector.size());
Vector itemsToRemove = new Vector();
itemsToRemove.add("value3");
itemsToRemove.add("value4");
//remove multiple values
vector.removeAll(itemsToRemove);
System.out.println("Size : "+vector.size());
//to remove all elements
vector.removeAllElements();
// or
vector.clear();
But instead of using Vector consider to use ArrayList since Vector is obsolete collection.
Read this : Why is Java Vector class considered obsolete or deprecated?
Also use generics Like ArrayList<String> idList = new ArrayList() if you store only String elements in list.
If you want to skip duplicates when adding elements in Vector, use the following code
Vector vector = new Vector() {
#Override
public synchronized boolean add(Object e) {
if(!contains(e)){
return super.add(e);
}
System.out.println("Element " + e +" is duplicate");
return false ;
}
};
But if you want to add only unique elements, use Set
Do completely remove the duplicated ids, you could use the following:
Set<String> ids=new LinkedHashSet<String>();
Set<String> duplicates=new HashSet<String>();
while (readFile.hasNextLine()) {
String id= readFile.nextLine();
if(!ids.add(id)) {
duplicates.add(id);
}
}
ids.removeAll(duplicates)
Note that unlike Vector, LinkedHashSet is not synchronized. In most cases this is not a bad thing, but in the case that you actually need it to be synchronized, wrap it using Collections.synchronizedSet()
READ the javadoc and pay attention to methods starting with remove http://docs.oracle.com/javase/6/docs/api/java/util/Vector.html. This should be you first approach not SO.
If you "want to remove multiple ids in Vector" do the following
ids = new Vector(new HashSet(ids))

Categories