I'm really good with VB and I have a project where I need to check an array. If the same item in an array exists twice or more it needs to be changed to an item that doesn't exist. Now I'm in a class where they're making us use Java for this project.
I was wondering what is the equivalent of a for each loop in Java? I checked the JavaDocs and it only had info for the regular for loop, I didn't notice any section that said anything about a for each loop.
It's more subtle in Java than VB. You can find the official docs in the Oracle documentation here (towards the bottom):
Java For Loops
The provided example is:
// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}
Hope that helps. Be careful not to remove or add elements inside the loop or you will get a Concurrent Modification Exception.
try
String arr [] = // you decide how this gets initialized
for (String obj: arr) {
}
This is called "iterating over collections". An array can be implicitly converted to a collection, so you can iterate over an array in the same way, using the "enhanced for-loop".
List<String> names = new LinkedList<>();
// ... add some names to the collection
for(name:names) {
System.out.println(name);
}
I'm not sure if VB has collections - they are a big part of Java and I recommend you look into them.
Of course this changes a bit in Java 8, although you'll notice a collection is still the backbone of forEach().
List<String> names = new LinkedList<>();
// ... add some names to the collection
names.forEach(name -> System.out.println(name));
A for each loop (also known as the enhanced for loop) is as follows:
for (String name : names) {
// here, the loop will work over each element of 'names',
// with the variable name with which to access each element
// being 'name', and output it
System.out.println(name);
}
A normal for loop is as follows:
for (int i = 0; i < max; i++) {
// here, i will iterate until max, then the loop will stop.
// any array access here has to be done manually using i, which increments.
}
If insertion order from the names array is important, keep adding the objects to a LinkedHashSet<String>, then with either a for loop or enhanced for loop or iterator, go over your list of names and add each of them to the LinkedHashSet. If the add method, passing in your name, returns false, generate a new name and add that.
If insertion order is not important, use a HashSet<String> instead.
At the end, convert back to an array if it is important (String[] bla = map.toArray(new String[0])), or output the toString() of the map.
Related
Below is a simple for loop I am using to try and go through and find the repeated ID's in a array list. The problem is that it only checks one index to the right so quite clearly if there is the same ID two, three or even four indexes across it will miss it and not report it as a repeated ID.
Obviously the goal of this code is to move through each index of the array list, get the ID and check if there are any other identical ID's.
Note for the below arraylist is...arraylist, the getId method simply returns the user ID for that array object.
for (int i=0; i<arraylist.size()-1; i++) {
if (arraylist.get(i).getId() == arraylist.get(i+1).getId()) {
System.out.println(arraylist.get(i).getId());
}
}
What I've tried and keep coming back to is to use two embedded for loops, one for iterating through the array list and one for iterating through an array with userIDs. What I planned on doing is checking if the current arraylist ID was the same as the array with 'pure' IDs and if it wasn't I would add it to the array of 'pure IDs. It would look something like this in psudocode.
for i<-0 i<arraylist size-1 i++
for j<-0 j<pureArray size j++
if arraylist.getId(i) != pureArray[j] then
increment pureArray size by one
add arraylist.getId(i) to pureArray
In practice perhaps due to my poor coding, this did not work.
So any opinions on how I can iterate completely through my arraylist then check and return if any the gotten IDs have multiple entries.
Thank you.
Looking at leifg's answer on this similar question, you can use two sets, one for duplicates and one for everything else, and you can Set#add(E), which "returns true if this set did not already contain the specified element," to determine whether or not the element is a duplicate. All you have to do is change the sets generics and what you are adding to them:
public Set<Integer> findDuplicates(List<MyObject> listContainingDuplicates)
{
// Assuming your ID is of type int
final Set<Integer> setToReturn = new HashSet();
final Set<Integer> set1 = new HashSet();
for (MyObject object : listContainingDuplicates)
{
if (!set1.add(object.getID()))
{
setToReturn.add(object.getID());
}
}
return setToReturn;
}
For the purpose of getting duplicates, nested for loop should do the job, see the code below. One more thing is what would you expect this nested for loop to do.
Regarding your pseudocode:
for i<-0 i<arraylist size i++
for j<-i+1 j<arraylist size j++
if arraylist.getId(i) != arraylist.getId(j) then
add arraylist.getId(i) to pureArray
1) Regarding j<- i+1, with every iteration you do not want to compare the same thing many times. With this set up you can make sure you compare first with others, then move to second and compare it to the rest (not including first because you already did this comparison) etc.
2) Incrementing your array every single iteration is highly impractical as you will need to remap and create a new array every single iteration. I would rather make sure array is big enough initially or use other data structure like another ArrayList or just string.
Here is a small demo of what I did, just a quick test, far no perfect.
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// create a test array with ID strings
ArrayList test = new ArrayList<>();
test.add("123");
test.add("234");
test.add("123");
test.add("123");
String duplicates = "";
for(int i = 0; i < test.size(); i++) {
for(int j = i+1; j < test.size(); j++) {
// if values are equal AND current value is not already a part
// of duplicates string, then add it to duplicates string
if(test.get(i).equals(test.get(j)) && !duplicates.contains(test.get(j).toString())) {
duplicates += " " + test.get(j);
}
}
}
System.out.println(duplicates);
}
}
Purely for the purpose of finding duplicates, you can also create a HashSet and iteratively add the objects(ID's in your case)to the HashSet using .add( e) method.
Trick with HashSet is that it does not allow duplicate values and .add( e) method will return false if the same value is passed.
But be careful of what values(objects) you are giving to the .add() method, since it uses .equal() to compare whatever you're feeding it. It works if you pass Strings as a value.
But if you're giving it an Object make sure you override .equals() method in that object's class definition (because that's what .add() method will use to compare the objects)
This question already has answers here:
How does the Java 'for each' loop work?
(29 answers)
Closed 9 years ago.
Method 1
ArrayList<String> list = new ArrayList<String>();
for (String s : list) {
write.append(s);
write.append('\n');
}
How is looping through an ArrayList this way possible? isn't this method only applicable for static usual arrays, for example : String[] list2 = new String[]{"1","2","3","4"}; ?
If I want to loop over the ArrayList<String> list, why not doing this for example:
Method 2
for (int i = 0; i < list.size(); i++) {
write.append(list.get(i));
write.append("\n");
}
I'm just not understanding how is it possible to use Method 1. Any explanation is welcomed.
ArrayList implements Iterable which makes it provide an Iterator object, which is then user by for loop.
Any class implementing Iterable would be usable in a for loop, just like an array.
The simplified for loop is made to look same for arrays and collections, but under the hood, it uses index for arrays and iterator for collections.
These are called for-each loops, and can be applied to both arrays and collections. Format:
for ([type] [var-name] : [array or iterable value]) {
...
}
To use a for-each loop, you only need to satisfy one of two conditions:
The iteration value is an array, or
the iteration value is an Iterable.
The biggest reason we do this is because List isn't the only Iterable that we can use in the loop, but it is the only one that can be indexed. This allows you to do generic iteration instead of locking yourself into a fixed, indexed list format.
For example, HashSet is not ordered, but I can still iterate over it in a for-each loop:
HashSet<String> strs = new HashSet<String>();
for (String str : strs) { ... }
I can also have a method take an Iterable instead of a List:
public static void printStrings(Iterable<String> strs) {
for (String str : strs) {
System.out.println(str);
}
}
There is no way for me to iterate over it using an index without first copying it into something else, like an array or a List.
Another important reason to use the for-each loop is that it compiles to using the Iterator off the list (via Iterable.iterator()), which allows for fail-fast iteration. This results in things like ConcurrentModificationExceptions to tell us that the collection was modified while we were iterating over it. For example, this will always throw a ConcurrentModificationException:
List<String> strs = ... ;
for (String str : strs) {
strs.remove(str);
}
But this won't:
List<String> strs = ... ;
for (int i = 0; i < strs.length(); i++) {
strs.remove(str);
}
This is good for multi-threaded applications because you're supposed to lock the list before you access it since most List implementations aren't designed for thread-safety, and iteration is never thread-safe without external synchronization, both with indexing and with Iterator. If one thread is iterating over it while another changes it, this can (not guaranteed, but can) throw a ConcurrentModificationException, which tells you that the list isn't properly locked. The indexed for could never give you this kind of information. Instead, it will just exhibit strange behavior like skipping elements.
There is an interface called Iterable which allows fast iteration. If something implements Iterable, fast iteration is allowed. The Iterable interface has one method, which returns an Iterator which can be used to iterate the elements.
The first is called an enhanced-for, or "for each". It is considered syntactic sugar for the traditional model of for statements - allowing you to iterate over every element in a collection - be that an array or anything in the Java Collections Framework.
There are two distinct differences between these types of loops:
The enhanced for statement indexes the value for you, storing it in the temporary variable as part of the declaration. Thus, you don't have to do things like val[i] or value.get(i) - this happens for you automatically.
You don't get to specify what you increment by in the enhanced for statement; you either iterate over all elements in the collection, or you terminate early via a break statement.
The reason that this can be iterated over using a standard array is defined in the JLS, specifically ยง14.14.2 - since an array doesn't implement Iterable, it converts it to a standard-behaving for statement.
...Otherwise, the Expression necessarily has an array type, T[].
Let L1 ... Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement.
The enhanced for statement is equivalent to a basic for statement of the form:
T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
VariableModifiers(opt) TargetType Identifier = #a[#i];
Statement
}
#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.
This is the for-each syntax: http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
The compiler will convert your code in method 1 to something like:
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String s = iterator.next();
write.append(s);
write.append('\n');
}
I just started using the enhance for-loop. I want to know if I can use this loop to copy an array. I want to iterate through every element of a certain array and copy it to a new one. It would also be nice to use the enhanced for-loop to instantiate my new array (instead of a typical for-loop). In my current implementation I do know how big I want the array to be, but for future reference I would like to know if I can do this, and if so, how.
My specific plans for what I'm doing might help to answer my question. What I am doing is retrieving a line of text from a text file then calling split( "," ) on that string - this returns an array of Strings. I want to store this array in memory so I can play with it later.
The way I understand the enhanced for-loop to work is that the first value is assigned the current position in the array and the second value is the array that is to be traversed.
I was wondering if there are other formats for for-loops, besides: for ( initialization; termination; iterate ) and for ( Object o : list[] ).
If you want to keep to the enhanced for loop for copying an array, there is one mayor problem: the enhanced for loop doesn't have a counter. Inserting elements into an array however requires a counter. So you could of course do this manually like so:
String[] array = {"A", "Bb", "c", "dD"};
String[] newArray = new String[array.length];
int i=0;
for(String stuff : array) {
newArray[i++] = stuff;
}
This is entirely possible but not really the idea behind the enhanced for loop.
More in line with the intention would be something like this:
String[] array = {"A", "Bb", "c", "dD"};
List<String> list = new ArrayList<String>();
for(String stuff : array) {
list.add(stuff);
}
String[] newArray = new String[list.size()];
list.toArray(newArray);
That way not only do you follow the idea behind the enhanced for loop, you also allow for the possibility that array.length() != newArray.length() (because, say, you filtered the array).
EDIT: as of Java 7, there are indeed only the two for loops you mentioned. This may change in future versions though if it seems sensible; after all, the enhanced for loop was only added in Java 5 (as can be seen here).
To my knowledge, there are only standard for(init; termination; iterataion) loops and for-each for(type o : iterable) loops.
First, knowing the size ahead of time shouldn't be a concern. For instantiating the new array use the original array's .length field: new String[original.length]; as shown below.
Moving along, for what you are doing, the standard for loop is appropriate for two reasons:
You would need to nest two for-each loops in order to iterate both
loops, making it more hassle than a standard for loop. (or add an externally defined counter, as in blalasaadri's solution)
More importantly, in the case of a primitive data type or a String, the variable declared before the : in the for-each loop represents the value of each successive element, and is not a reference to the actual element. As such, any changes to the variable are gone once the loop iterates. I'm not sure if this holds for 'normal' objects (ie: not String), as I've not tried, though I want to find out now.
To illustrate:
String[] sArr = {"foobar"};
for(String s : sArr){
s = "openbar";
}
is the equivalent of:
String[] sArr = {"foobar"};
String s = sArr[0];
s = "openbar";
Sadly, for sArr[0], there is no open bar, same old foobar.
As for solutions, if you can import java.util.Arrays; then try:
String[] copyStrings = Arrays.copyOf(arrStrings, arrStrings.length);
Or, if you need to roll your own:
public String[] copyArray(String[] original){
String[] dupe = new String[original.length]; //I assume you want equal length
for(int i = 0; i < original.length; i++){
dupe[i] = original[i]; //single iterator traverses both arrays
}
return dupe;
}
// copy contents of Object[] arr1 into Object[] arr2
arr2 = new int[arr1.length];
int i=0;
for(Object c:arr1){ //store an element of arr1 in c iteratively
arr2[i] = c;
i++;
}
I have an ArrayList of type String. I want to determine whether any element of this ArrayList starts with a specified string and if the ArrayList contains this element, then I want to get the index of this element. In addition, I do not want to loop this ArrayList to get the index of that element.
For example :
ArrayList<String> asd = new ArrayList<String>(); // We have an array list
//We filled the array list
asd.add("abcc trtiou");
asd.add("aiwr hiut qwe");
asd.add("vkl: gtr");
asd.add("aAgiur gfjhg ewru");
Now, I want to get the index of the element vkl: gtr by using vkl: without looping array list.(searching also should be case insensitive, so, using vkl: and VkL: should give the index of vkl: gtr)
How can I do this ?
Thanks in advance.
You have to loop the ArrayList. You cant possibly access just a single index and be guaranteed it is what you're looking for.
Also, you should consider using another data structure if a lot of searching is involved. Searching an ArrayList takes O(n)time while something like a red-black tree can be done in O(log n).
If you know before program execution the strings used to locate the items in the structure, consider using a HashMap. You can access the items in O(1).
If none of these solutions suit your particular problem expand on your answer with what you're trying to do, we could provide a better answer as to how you'd locate your items with minimal search time.
This is as far as you can get with your requirement if you're not looking to perform loop and search against the string objects held in the arraylist.
if(asd.contains("vkl: gtr"))
{
int index=asd.indexOf("vkl: gtr");
}
or simply:
int index = Arrays.binarySearch(asd.toArray(), 0, asd.size()-1, "vkl: gtr");
If performing loop in your calling method is what you're looking to avoid then, alternative you can create a class which extends ArrayList and have a method which does the index lookup.
class MyArray extends ArrayList<String>
{
public int getIndexOf(String o)
{
for (int i = 0; i < size(); i++)
{
if (get(i).contains((String) o)) return i;
}
return -(size() - 1);
}
}
Then from your calling program do:
public void foo()
{
MyArray asd = new MyArray();
asd.add("abcc trtiou");
asd.add("aiwr hiut qwe");
asd.add("vkl: gtr");
asd.add("aAgiur gfjhg ewru");
int index = asd.getIndexOf("vkl:");
}
for(int i=0; i < asd.size(); i++) {
String s = asd.get(i);
//search the string
if(found) {
return i
}
}
return -1
I don't really understand if you are looking for something like key-value pairs or single string entry search.
If you are looking for the first one you should use Map instead of a simple array if you want to search for a key
Here you can put a pair using
put(Object key, Object value)
and the getting the value of a specified key with
get(Object key)
If you are looing only for a quick way of finding a part of string into an array you have to read all indexes and compare strings one by one using stringToCompare.equalsIgnoreCase(otherStringToCompare). Note that this will throw an exception if stringToCompare is NULL
This question already has answers here:
Why does the foreach statement not change the element value?
(6 answers)
Closed 5 years ago.
Ok, so I'm tyring to iterate through an ArrayList and remove a specefic element. However, I am having some trouble using the For-Each like structure. When I run the following code:
ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)
for(String t : arr)
{
t = " some other value "; //hoping this would change the actual array
}
for(String t : arr)
{
System.out.println(t); //however, I still get the same array here
}
My question in, how can I make 't' a pointer to 'arr' so that I am able to change the values in a for-each loop? I know I could loop through the ArrayList using a different structure, but this one looks so clean and readable, it would just be nice to be able to make 't' a pointer.
All comments are appreciated! Even if you say I should just suck it up and use a different construct.
I think the best approach may be to use a for loop.
ArrayList<String> arr = new ArrayList<String>();
for (int i = 0; i < arr.size(); i++) {
String t = arr.get(i);
if (// your condition is met) {
arr.set(i, "your new value");
}
}
The problem is that you're trying to change the loop-scoped reference t to let it point to a new String instance. This ain't going to work. It does not refer the actual entry in the arraylist. You need to change the actual value of the reference. If String was mutable and provided a fictive set() method for that, you could in theory do
for (String t : arr) {
t.set("some other value");
}
or so, but that's not possible as it is immutable. Better get a handle of the entrypoint in the array itself using the normal for loop:
for (int i = 0; i < arr.size(); i++) {
arr.set(i, "some other value");
}
If you insist in using the enhanced for loop, then you need to replace String by StringBuilder, which is mutable:
for (StringBuilder t : arr) {
t.delete(0, t.length()).append("some other value");
}
Remember, Java is pass-by-value, not pass-by-reference.
For-each doesn't give you an index pointer, so you just can't use it to change an immutable value.
Either use a for-loop with an index or use a mutable type (like StringBuffer, not String)
An array of objects (like strings) in Java is a contiguous block containing an ordered series of references. So, when you have an array of 4 strings, what you really have is 4 references stored IN the array, and 4 string objects that are outside of the array but are referenced by its 4 elements.
What the for-each construct in Java does is create a local variable and, for each iteration, copy into that local variable the reference from the array cell that corresponds to that iteration. When you set the loop variable (t = " some other value") you are putting a reference to a new string, "some other value", into the local variable t, not into the array.
The contrasts with some other languages (like Perl) where the loop variable acts like an alias to the array/list element itself.
Your code is re-written by the compiler as something like this:
ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)
for (final Iterator <String> i = arr.iterator(); i.hasNext();) {
String t;
t = i.next();
t = " some other value "; // just changes where t is pointing
}
To do what you want you would have to write the for loop like this:
for (final ListIterator<String> i = arr.iterator(); i.hasNext();) {
final String t;
t = i.next();
i.set("some other value");
}
Iterator does not have the set method, only ListIterator does.
Basically you want to remove the String t from the list arr. Just do a arr.remove(t) and you could be done. But you can't do it while iterating over the same list. You'll get an Exception if you try to modify the list this way.
You have two options:
clone your list, iterate through the clone and remove the 'specific' String from the original list
create a list for delete candidates, add all 'specific' Strings to that list and, after iterating through the original list, iterate through the wastebin and remove everything you've collected here from the original list.
Option 1 is the easist, the clone can be made like:
List<String> clone = new ArrayList<String>(arr);
You seem to misunderstand how objects/references work in Java, which is pretty fundamental to using the language effectively. However, this code here should do what you want (apologies for the lack of explanation):
ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)
for(int i = 0; i < arr.size(); i++)
{
arr.set(i, " some other value "); // change the contents of the array
}
for(String t : arr)
{
System.out.println(t);
}
I believe, this is not related to immutable or mutable.
t = " some other value "; //hoping this would change the actual array
t does not hold the reference to actual object. Java copies the value from arraylist and puts that value into t so array list value does not get affect.
HTH
This has been answered well. Still here is my suggestion. The var t inside loop is only visible there. It will not be seen outside the loop. You could do t.set() if it was not String.
Use a StringBuffer rather than plain strings. This way the string within is mutable.
Strings are immutable. If you had a mutable type like StringBuilder/Buffer, you could change the string in your iteration. You do have references, remember.