Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I was browsing through questions regarding continue keyword to get a better understanding of it and I stumbled upon this line in this answer
These can be maintenance timebombs because there is no immediate link between the "continue"/"break" and the loop it is continuing/breaking other than context;
I have this for loop:
for(Object obj : myArrayList){
if(myArrayList.contains(someParticularData)){
continue;
}
//do something
}
Now, my question is - Is it okay to use continue in the manner that I have done above or does it have any issues? If yes, what is the alternative approach that I can follow? Any kind of guidance would help. Thank you.
Update: My objective in this particular situation would be to iterate over a Collection ( ArrayList, in this case), and check if that contains some particular data and skip that iteration if it is true.
I was pointed out that myArrayList.contains(someParticularData) is a one time operation and that it would be better off to perform that check outside the loop, which is what I was looking for. Also, I learnt that if I can use continue based on some condition if(someConditon), I can very well avoid it by using if(!someCondition).
for(Object obj : myArrayList){
if(someCondition){
continue;
}
//do something
}
can be replaced with:
for(Object obj : myArrayList){
if(!someCondition){
//do something
}
}
IMHO, as far as you don't have a lot (like 2-3 continue/break/return), maintenance will be fine.
This code is of little use
for(Object obj : myArrayList) {
// You're checking again and agian the condition that's loop independent
if(myArrayList.contains(someParticularData)){
continue;
}
//do something
}
A more effective implementation is (check whether you need the loop at all first)
if (!myArrayList.contains(someParticularData))
for(Object obj: myArrayList) {
//do something
}
continue is convenient in conditions like that:
for(Object obj : myArrayList) {
// Check for each item: do we need to proceed this item
if (someArrayList.contains(obj))
continue;
//do something
}
Whenever you are looping on some value range, you are processing on each of the value comes between the initial and final one...
For example if you are making addition of odd numbers.
it is convenient to use loop which will be incremented by 2 rather than continuing for each odd value,
for (int i = 0; i < 100 ; i=i+2){
// do addition
}
but if you are modifying your value that is being checked within the loop, than continue or break is good practice to implement.
for example,
boolean flag = false;
// flag will be modified in some iteration of loop, but you don't know which.
for ( int i = 0 ; i < 100 ; i++ ) {
if ( flag ) {
continue;
}
// flag modified somewhere..
}
Related
asnafList is my list and getIc_number is my getter below is my code
asnafList.get(0).getIc_number();
I am trying to make sort of an authenticating feature for my apps and I use the above code in my if statement for the button. That code only get the 0 position of the list. So my question is, is there a way to get all of the position is the list to compare with the input from the user using the if statement?
int number;
for(int i = 0; i < asnafList.size(); i++) {
number = asnafList.get(i).getIc_number();
if(number == YOUR_COMPARABLE_NUMBER) {
// Compare and do anything here
}
}
As Kushal answered, a for loop is useful for this. But I usually use a for each loop in this scenario. Not sure what type of objects are in the asnafList, but it will look something like this:
for(AsnafObject a : asnafList) {
if(a.getIc_number() == YOUR_COMPARABLE_NUMBER) {
// do stuff
}
}
When you do this for loop, you basically iterate through every object in the asnafList, where AsnafObject is the classtype of your asnafList and a is the object which you can use to call any non-static methods of AsnafObject (or however your class is called)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
So in an attempt to keep up with the times, I would like to learn what I can about Java 8's new functional operations. Beyond the opinions of which looks nicer, which is totally opinion based, would someone like to describe in detail the positives(and possibly negatives) in using Java 8's new functional programming style to iterate arrays?
This is what I mean:
Pre-Java 8:
for(Object item: itemList){
item.doSomething();
}
Java 8:
itemList.stream().forEach((item) -> {
item.doSomething();
});
The answers have enlightened me, so I will write something to demonstrate it's potential.
static int pos = 0;
public static void main(String[] args) {
List<Worker> workers = Arrays.asList(new Worker[1000]);
workers.replaceAll(worker -> new Worker(pos++));
workers.parallelStream().forEach(Worker::startJob);
}
public static class Worker {
final int pos;
public Worker(int pos) {
this.pos = pos;
}
public synchronized void startJob() {
try {
wait(100);
} catch (InterruptedException ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
System.out.println("Finished... " + pos);
}
}
Only a partial answer, but the general point of the iterators is moving from external iteration to internal iteration. The foreach just a replacement, but consider something like the following (from Java 8 Lambdas) simulating the throwing of two dice:
public Map < Integer, Double > parallelDiceRolls() {
double fraction = 1.0 / N;
return IntStream.range( 0, N) .parallel()
.mapToObj( twoDiceThrows())
.collect( groupingBy( side -> side, summingDouble( n -> fraction)));
}
This is running a parallel operation against the stream, removing all external iteration requirements and all manual threading requirements. It replaces 50-60 lines of code.
It also moves from a focus on how to accomplish something (such as the OP's pre-Java 8 example) to what to accomplish.
Consider a Artist class that has an .isFrom(String) method. In the OP's first example, to count how many are from Liverpool, the code would be something like:
int count = 0;
for (Artist artist : allArtists) {
if (artist.isFrom("Liverpool")) {
count++;
}
}
Notice that the the desire to accumulate is lost in the loop and the filtering. Contrast with:
allArtists.stream()
.filter(artist -> artist.isFrom("Liverpool")
.count();
Now the logic is clear -- a filtering and a count. The iteration is now internal rather than external.
There are many additional examples, rationales, and preferences. But I think it is more than "beauty" -- it is a focus on the what, not the how when one considers iteratation.
Let's assume that we have a for-loop that will loop through a collection or array of Strings. In that case, I am searching for a specific keyword (ex. hey) here's how I usually achieve that:
for (String result : strings)
{
if (result == "hey")
{
// Do something with that.
break;
}
}
Now, the question arises from that code snippet is, should I place a keyword (return or break) when the if-statement returns true so the loop will not continue? If not, what will happen and what's the correct way of going about it.
Edit: What happens when you use break and return? What's the difference?
Let's put your code inside a method:
private void foo()
{
for (String result : strings)
{
if (result.equals("hey"))
{
// Do something with that.
break;
}
}
bar();
}
If you use break;, the loop will terminate and bar will be reached. If you use return, the method will terminate and bar won't be executed.
Note that comparing strings should be done using equals, == compares references and not content.
If you know the word can only be found once you can surely place an break; statement so the loop won't continue after finding the match.
If you can have more than one match and you want the if block to be executed for each of those matches you should NOT put the break statement since it will stop the execution of the loop after the first match is found.
I have a program and its processing rather large amounts of data. It is comparing one static string arraylist to another checking whether a string is contained in it.
But what happens is after processing lets say 40k+ strings it begins to fail on the checking. By fail I mean it begins to not recognize that a string already exists in the other?
Is there a reason for this or is the arraylist simply too large?
Thanks
EDIT
for (int i = 0; i < arraylist1.size(); i++) {
boolean enter = true;
for (int x = 0; x < arraylist2.size() && enter; x++) {
if (arraylist1.get(i).getString().matches(arraylist2.get(x))) {
enter = false;
}
}
if (enter) {
//do something
}
}
EDIT****
Off-topic to the question but using .equals() instead of .matches() improves the performance MASSIVELY.
The simple answer is: no.
ArrayLists do not lose what is in them.
Your symptoms could be caused by a number of things, including threading/synchronization issues, subtle differences in the string, etc.
You should consider using a HashSet anyway though. It will make the "contains" check much much faster.
Using HashSet all your code above becomes:
List<String> list;
Set<String> set;
for (String str: list) {
if (!set.contains(str)) {
//do something
}
}
Much simpler and incredibly faster.
If you do need to use lists you can do the same thing but having both collections as List, the API doesn't change but performance will.
I'm pretty new to Java and trying to figure out how I would convert the below code
to a for loop or a for each loop.
do {
testPages.push(testParentPage);
if(homePage != null && testParentPage.getPath().equals(homePage.getPath())){
isParent = true;
break;
}
} while((testParentPage = testParentPage.getParent()) != null);
Any help is greatly appreciated! Thanks!
It can be rewritten in a for loop like this:
for (; testParentPage != null; testParentPage = testParentPage.getParent()) {
testPages.push(testParentPage);
if(homePage != null && testParentPage.getPath().equals(homePage.getPath())){
isParent = true;
break;
}
}
Thought I must admit that I don't know if it serves any benefit.
Try
for(; testParentPage != null; testParentpage = testParentPage.getParent()) {
...
}
The for loop structure is (variable initialization; boolean test; assignment) - usually the variable is an integer, the test is a < or >, and the assignment is an increment, but this doesn't need to be the case.
Actually the do .. while loop looks to be perfectly appropriate in this case. A for or foreach loop would be the tool of choice if you have a "normal" collection or something giving you an iterator. But in this case (navigating a tree structure upward) using a for loop would IMHO actually be confusing.
In addition to that, the condition of a for loop is always evaluated before execution of the loop body. Since you need to execute the body at least once this would make things more difficult and/or complex.
Edit: Of course it might actually make sense to perform the null-ness check at the beginning of the loop, since you call a method on testParentPage in the loop body.
Re: for-each loop.
A for each loop iterates over a Collection or array (see docs) so you won't be able to (immediately) convert your do-while loop to a for-each loop, since you're iterating over a custom-defined hierarchy.
If you had a List<TestPageParent> (or whatever the type name is for that) it would work. So would TestPageParent[]. Or Collection<TestPageParent>.