Iterating with two iterators - java

I have two array lists which have a different number of items in them.
The first iteration works well, but when it moves on the the next, nothing happens which I suspect is because the second iterator has no next. Is there anyway to reset it?
Iterator<Integer> itID = ID.iterator();
Iterator<String> itTable = Table.iterator();
Iterator<String> itColumn = Column.iterator();
while(itID.hasNext()){
int i = itID.next();
System.out.println(i);
while(itTable.hasNext()){
String SQL = "select " + itColumn.next() + " from " + itTable.next() + " where id=" + i;
System.out.println(SQL);
}
}

I think the problem is that you have to move inside the first cycle the instantiation of the iterators itTable and itColumn.
Iterator<Integer> itID = ID.iterator();
while (itID.hasNext()) {
// Every time you ask for an iterator, you obtain a new one.
Iterator<String> itTable = Table.iterator();
Iterator<String> itColumn = Column.iterator();
int i = itID.next();
System.out.println(i);
while(itTable.hasNext()){
String SQL = "select " + itColumn.next() + " from " + itTable.next() + " where id=" + i;
System.out.println(SQL);
}
}
So the best way to "reset" an iterator is to ask to the aggregate for a new instance of the iterator itself.

The iterators used in the nested loop should be initialized inside of the first loop so they get reset every time the outer loop iterates.
But you can (and should) just use a for loop to iterate through an ArrayList:
for (int i = 0; i < myList.size(); i++) {
// use myList.get(i)
}
Or just
for (String s : myList) { // Change string to whatever type your list is holding
// use 's'
}
The second loop there is called a for each loop. It is designed for iterating through lists and arrays. For your purpose this one will not work because you're iterating through 2 lists, but I thought I'd bring it up anyway. You should use the first for loop.

A little bit past the scope of the question, but this is my thoughts.
Iterating through two lists which you assume to be the same size, is asking for trouble. If these two values are supposed to be coupled together, then well.. couple them together. The following class can do that:
class SQLField
{
private String tableName;
private String columnName;
public SQLField(String tableName, String columnName) {
this.tableName = tableName;
this.columnName = columnName;
}
public getSelect() {
return "select " + this.columnName + " from " + this.tableName
}
}
This makes the using code:
Iterator<Integer> itID = ID.iterator();
while (itID.hasNext()) {
// Every time you ask for an iterator, you obtain a new one.
Iterator<SQLField> fields = SQLFields.iterator();
int i = itID.next();
System.out.println(i);
for(SQLField field : fields) {
String SQL = field.getSelect() + " where id = " + i;
System.out.println(SQL);
}
}
This is a much better approach in my opinion.

Related

How to efficiently get items from a list without using get?

For example my current code which finds all elements in the list with a size of 8:
public static void printFamiliesOfLength(int theSize,
List<AnagramFamily> theFamilies,
PrintStream theOutput) {
theOutput.println("Families of length: " + theSize);
theOutput.println("-----------------");
for(int i = 0; i < theFamilies.size(); i++) {
if(theFamilies.get(i).getFamilySize() == theSize) {
theOutput.print(theFamilies.get(i).getCan() + ": ");
theOutput.println(theFamilies.get(i));
}
}
}
What I am trying to do is the same thing, but do it without using .get. Right now my program is taking 10 seconds to execute, I'd like to bring that down to like 1 or 2 seconds. Thinking of using iterator but not sure if that would help since it is sort of iterating through anyways?
Use foreach loop:
for(AnagramFamily anagramFamily: theFamilies) {
if(anagramFamily.getFamilySize() == theSize) {
theOutput.print(anagramFamily.getCan() + ": ");
theOutput.println(anagramFamily);
}
}
This will not use get, but I don't know if the problem is with get method.
For performance issue that can avoid situation when you passed big LinkedList and use get(i) and each time iterating on whole list.
If you like to use Java 8, you can do something like this (example is list with Strings):
List<String> filteredNames =theFamilies.stream().filter(x ->
x.length()==theSize).collect(Collectors.toList());
filteredNames.forEach(System.out::print);
You can create a AnagramFamilyCollection class to be used instead of the list where you could save the familySize in a Map key.
public class AnagramFamilyCollection {
private List<AnagramFamily> anagramFamilies;
private Map<Integer, List<AnagramFamilies>> familiesSizes;
public void insert(AnagramFamily anagramFamiliy) {
anagramFamilies.add(anagramFamiliy);
addToMap(familiesSizes, anagramFamiliy);
}
private void addToMap(Map<Integer, List<AnagramFamilies>> map, AnagramFamily anagramFamiliy) {
List<AnagramFamily> list =
familiesSizes.getOrDefault(anagramFamiliy.getFamilySize(), new ArrayList());
list.add(anagramFamiliy);
familiesSizes.put(anagramFamiliy.getFamilySize(), list);
}
public List<AnagramFamily> getBySize(int size) {
return familiesSizes.get(size);
}
}
Then, you could use it in your method like this.
List<AnagramFamily> theFamilies = anagramFamilyCollection.getBySize(theSize);
for(int i = 0; i < theFamilies.size(); i++) {
theOutput.print(theFamilies.get(i).getCan() + ": ");
theOutput.println(theFamilies.get(i));
}

Get Hashset Key

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public static void printNumWordsDiscovered( HashMap<String,Integer> vocab, HashSet<String> dictionary ) {
HashMap <String,Integer> Combine = new HashMap <String,Integer> ();
Iterator iterVoc = vocab.entrySet().iterator();
List<String> Dic = new ArrayList<String>();
int i = 0;
double actual = 0.0;
double token = 0.0;
while(iterVoc.hasNext()){
Map.Entry iterVocE = (Map.Entry)iterVoc.next();
if (dictionary.contains(iterVocE.getKey().toString())){
int Value = (int) iterVocE.getValue();
actual += 1;
token += Value;
Combine.put(iterVocE.getKey().toString(), Value);
}
}
for(String s: dictionary.KeySet()){
if (Combine.contains(dictionary.get(s).toString())){
System.out.println("Dicovered " + dictionary.get(s) + " ( count " + Combine.get(dictionary.get(s)) + " )");
}
}
}
I am trying to iterate through a HashSet and I get errors concerning my .get() method. How do you get a key in a HashSet?
A HashSet is backed by a HashMap. I want to mention this first, because what manouti said isn't exactly true. A HashSet does have a key; you just doesn't explicitly know about the key from outside the HashSet (or rather you don't call it the key, you call it the value outside of the HashSet).
In fact, the key in the internal HashMap is the value you use in HashSet#add(E). The code for HashSet#add(E):
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
where PRESENT is just a dummy object for the value:
private static final Object PRESENT = new Object();
What you want to do, is call the iterator for HashSet to iterate over all the keys. Per the java.util.HashSet#iterator documentation:
Returns an iterator over the elements in this set. The elements are returned in no particular order.
So this is the equivalent of getting the internal HashMap, getting the HashMap#keySet, and then getting an iterator over that. Not that it matters, but that is exactly how the internal code of HashSet actually does it:
public Iterator<E> iterator() {
return map.keySet().iterator();
}
So that might be a little more explanation than you were looking for, but to your issue:
There is no HashSet#get function, there is no HashSet#KeySet function, there is no HashMap#contains function so I recommend you read through the HashSet documentation at http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html and HashMap documentation http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html before going any further. When in doubt, read the documentation. In Java you have the unique benefit of dealing with an API that is very, very well documented. If you choose not to use it, then its wasted.
In order to "get" anything out of a HashSet you have to have the object that results in the same hashCode anyway...so I'm not sure I quite understand the logic for what you are doing. In other words, if you already have the object, you don't need to get it from the HashSet.
Anyway, the last 6 lines of your code can be changed to this:
for(String s: dictionary.iterator()){
if (Combine.containsKey(s)){
System.out.println("Dicovered " + s + " ( count " + Combine.get(s) + " )");
}
}
You can use Iterator of HashSet.
Iterator it = dictionary.iterator();
String element;
while ( it.hasNext() ) {
element = ( String ) it.next();
if ( Combine.contains(element) ){
System.out.println("Dicovered " + element + " ( count " + Combine.get(element) + " )");
}
}
Iterate over HashSet by using iterator method which returns Iterator.
Use Iterator Pattern instead of:
for(String s: dictionary.KeySet()){
if (Combine.contains(dictionary.get(s).toString())){
System.out.println("Dicovered " + dictionary.get(s) + " ( count " + Combine.get(dictionary.get(s)) + " )");
}
}
Good luck!

Iterating through double collections in Java

I'm a Java beginner, so please bare with possibly silly or trivial questions.
I have two collections (array lists or hashtables) and I want to compare each and every element of the first collection to each and every element of the second collection.
I wrote the following code, but this only compares element 1 of the first collection to element 1 of the second collection, element 2 of the first collection with element 2 of the second collection, etc., so I am missing most of the comparisons that I want to make. Can you please help me out?
public class IteratorDemo_1 {
public static void main(String args[]) {
// Create two array lists:
ArrayList alLetters = new ArrayList();
ArrayList alNumbers = new ArrayList();
// Add elements to the array lists:
alLetters.add("C");
alLetters.add("B");
alLetters.add("Z");
alLetters.add("X");
alNumbers.add("1");
alNumbers.add("6");
alNumbers.add("3");
alNumbers.add("7");
// Use iterator to display the contents of 'al':
System.out.println("Original contents of 'alLetters': ");
Iterator itrL = alLetters.iterator();
System.out.println("Original contents of 'alNumbers': ");
Iterator itrN = alNumbers.iterator();
while(itrL.hasNext()){
while(itrN.hasNext()){
Object elementL = itrL.next();
Object elementN = itrN.next();
boolean result = elementL.equals(elementN);
System.out.println(result);
System.out.println(elementL + " ");
System.out.println(elementN + " ");
}
}
System.out.println();
}
}
while(itrL.hasNext()){
Object elementL = itrL.next();
while(itrN.hasNext()){
Object elementN = itrN.next();
boolean result = elementL.equals(elementN);
System.out.println(result);
System.out.println(elementL + " ");
System.out.println(elementN + " ");
}
itrN = alNumbers.iterator();
}
Try the following:
while(itrL.hasNext()){
Object elementL = itrL.next();
Iterator itrN = alNumbers.iterator();
while(itrN.hasNext()){
Object elementN = itrN.next();
boolean result = elementL.equals(elementN);
System.out.println(result);
System.out.println(elementL + " ");
System.out.println(elementN + " ");
}
}

Getting values from one Array List using objects of another array list java

I have 3 ArrayLists.
Students (ID, Name, Program)
Courses (ID, Name, Credit Hours)
StudentCourses (StudentId, CourseID)
I am searching from StudentCourses by passing the StudentID and getting the courses registered with his/her name.
My StudentCourse ArrayLIst has objects like this
49 (Student ID)
CS233(Course ID)
49 (Student ID)
CS231(Course ID)
When a user searches for a student, say I'm searching for Johnna with her registration number 49.
The result is
Reg ID: 49
Name : Johnna
Program: BSCS
Courses Registered:
CS233
CS231
Which is fine. But, what I really need to do is get the name of the course using the course IDs that appear in the search info of Johnna. The Course ArrayList looks like this:
CS233
OOP
BSCS
CS231
ALgorithms
BSCS
I tried this code but it didn't seem to work. It keeps giving either garbage values or it just prints all Course names until there is a null exception:
if (myStudent == null) {
System.out.print("No Record Was Found");
} else {
System.out.print("Student ID: " + myStudent.getID() + "\nFull Name: " + myStudent.getName() + "\nProgram: " + myStudent.getProgram() +
"\nTotal Credit Hours: " + (Integer.parseInt(myStudent.getTotalCreds())) * 3420 + "Rs" + "\nCourses Registered:\n");
}
for (int i = 0; i < studCourseList.size(); i++) {
if (studCourseList.get(i).getSid().equals(ID)) {
System.out.print("- " + studCourseList.get(i).getCid() + "\n");
for (int j = 0; j < CoursesList.size(); j++) {
if(CoursesList.get(i).getID().equals(studCourseList.get(i).getCid())){
System.out.print("- " + CoursesList.get(i).getName() + "\n");
break;
}
}
}
}
The upper portion is bringing the Student info, the first loop is for the Courses registered against the student ID, and the second loop is not working.
Note that all objects are on different lines.
Well for starters, remove the semicolon after this if statement!
if(CoursesList.get(i).getID().equals(studCourseList.get(i).getCid()))
If that doesn't solve your problem, we're going to need more information about what studCourseList and CoursesList is. My inclination would be to guess that in your second loop you should use j like so:
if (CoursesList.get(j).getID().equals(studCourseList.get(i).getCid()))
But without explicit knowledge of your classes I can't be sure if that is correct.
In your nested for loop you use 'j' as a counter but inside that loop you reference 'i'.
for (int j = 0;j<CoursesList.size(); j++){
if (CoursesList.get(i).getID().equals(studCourseList.get(i).getCid()));
{
System.out.print("- " + CoursesList.get(i).getName() + "\n");
break;
}
It looks like
.equals(studCourseList.get(i).getCid()
should use 'j' as a reference otherwise you are not actually going through the studCourseList and are just comparing the same two items over and over.
I suggest you to use Map in place of List in this situation where Id is treated as key and POJO as its value.
HashMap is more faster than List in search.
Sample code:
class Student {
private String id;
private String name;
private String program;
// getter setter
}
class Course {
private String id;
private String name;
private int creditHours;
// getter setter
}
class StudentCourses {
private String studentId;
private String courseId;
// getter setter
}
Map<String, Student> students = new HashMap<String, Student>();
Map<String, Course> courses = new HashMap<String, Course>();

Why do my array.size() give wrong value?

I have an instance of ArrayList named array.
When I parse some JSON data it will store it all in array.
When I do a System.out.println(array); it will list a long list of items, around 30, but when I write System.out.println(array.size); it will give the value one.
How come it only gives me the value 1 when the list contains at least 30 values?
My code for this:
public void setLocationName (String name) {
array = new ArrayList<String>();
array.add(name);
System.out.println(array); //This return a long list
System.out.println(array.size()); //But this only return the value 1
}
public String[] getLocationName() {
String tArray[] = null;
for (int i = 0; i < array.size(); i++){
System.out.println(i);
tArray = array.toArray(new String[i]);
}
return tArray;
}
}
The long list :
[Brunnsparken, Göteborg]
[Brunnsgatan, Göteborg]
[Brunnslyckan, Lerum]
[Brunnsbotorget, Göteborg]
[Brunnsnäs, Ulricehamn]
[Brunnshult, Mellerud]
[Brunnsdal, Skövde]
[Brunns skola, Ulricehamn]
[Brunnsgården, Kungälv]
[Brunns kyrka, Ulricehamn]
[Boråsparken, Borås]
[Stadsparken, Ulricehamn]
[Lysekilsparken, Lysekil]
[Mössebergsparken, Falköping]
[Dalaborgsparken, Vänersborg]
[Rösparken, Åmål]
[Lillhagsparken Norra, Göteborg]
[Lillhagsparken Södra, Göteborg]
[Sylte Ryrbäcksparken, Trollhättan]
[Skogstomtsparken, Borås]
[Svinesundsparken, Norge]
[Håjumsparken, Trollhättan]
[Eriksdalsparken, Bollebygd]
[Fridhemsparken, Lidköping]
My result will be that only one item from the list will be returned in the tArray but I wanna return the whole list.
How to solve this?
Java doesn't understand Json and basically what you're doing is add a string to an array
this.array.add(name); ---> add one value to the array, therefore the size is just one
you may need to use a specific Json library to parse the data in to an java arraylist.
regards
Look like you need to parse the String into pairs.
Looks to me like a Map might be the most appropriate structure to store the data in - I presume the first part from the value is unique.
Regex is probably the best approach to parsing the data:
public static void main(String[] args) {
final String data = "[Brunnsparken, Göteborg]\n"
+ "[Brunnsgatan, Göteborg]\n"
+ "[Brunnslyckan, Lerum]\n"
+ "[Brunnsbotorget, Göteborg]\n"
+ "[Brunnsnäs, Ulricehamn]\n"
+ "[Brunnshult, Mellerud]\n"
+ "[Brunnsdal, Skövde]\n"
+ "[Brunns skola, Ulricehamn]\n"
+ "[Brunnsgården, Kungälv]\n"
+ "[Brunns kyrka, Ulricehamn]\n"
+ "[Boråsparken, Borås]\n"
+ "[Stadsparken, Ulricehamn]\n"
+ "[Lysekilsparken, Lysekil]\n"
+ "[Mössebergsparken, Falköping]\n"
+ "[Dalaborgsparken, Vänersborg]\n"
+ "[Rösparken, Åmål]\n"
+ "[Lillhagsparken Norra, Göteborg]\n"
+ "[Lillhagsparken Södra, Göteborg]\n"
+ "[Sylte Ryrbäcksparken, Trollhättan]\n"
+ "[Skogstomtsparken, Borås]\n"
+ "[Svinesundsparken, Norge]\n"
+ "[Håjumsparken, Trollhättan]\n"
+ "[Eriksdalsparken, Bollebygd]\n"
+ "[Fridhemsparken, Lidköping]";
final Pattern pattern = Pattern.compile("\\[([^,]++),\\s++([^\\]]++)\\]");
final Matcher matcher = pattern.matcher(data);
final Map<String, String> items = new TreeMap<>();
while (matcher.find()) {
items.put(matcher.group(1), matcher.group(2));
}
for (final Entry<String, String> entry : items.entrySet()) {
System.out.println(entry);
}
}
Output from this:
Boråsparken=Borås
Brunns kyrka=Ulricehamn
Brunns skola=Ulricehamn
Brunnsbotorget=Göteborg
Brunnsdal=Skövde
Brunnsgatan=Göteborg
Brunnsgården=Kungälv
Brunnshult=Mellerud
Brunnslyckan=Lerum
Brunnsnäs=Ulricehamn
Brunnsparken=Göteborg
Dalaborgsparken=Vänersborg
Eriksdalsparken=Bollebygd
Fridhemsparken=Lidköping
Håjumsparken=Trollhättan
Lillhagsparken Norra=Göteborg
Lillhagsparken Södra=Göteborg
Lysekilsparken=Lysekil
Mössebergsparken=Falköping
Rösparken=Åmål
Skogstomtsparken=Borås
Stadsparken=Ulricehamn
Svinesundsparken=Norge
Sylte Ryrbäcksparken=Trollhättan
You can the access the items by looping (as above) or by getting values from the Map by key. The TreeMap I have used will sort the data by key, you can also use a LinkedHashMap to store the data in insertion order.
You could also store the items in a List of tuple like structures.
public void setLocationName (String name) {
array = new ArrayList<String>();
array.add(name);
System.out.println(array); //This return a long list
System.out.println(array.size()); //But this only return the value 1
}
You are creating a new ArrayList each time you call this method:
array = new ArrayList<String>();
You could just remove the above line, however I suggest you rename the method as this is no longer a setter and you are in fact now adding to an existing list each time you call this method.
I suggest what you want to do is build your List before parsing to the setter, perhaps using a foreach loop (I'm not sure what kind of object you are working with) and simplify your setter (setLocationName) to accomodate.
So it would become:
public void setLocationName(ArrayList<String> names)
{
this.array = names;
System.out.println(array); //This return a long list
System.out.println(array.size()); //But this only return the value 1
}

Categories

Resources