java arraylist iteration - java

Is this going to cause unpredictable behavior?
ArrayList<X> x = new ArrayList<>();
//x.add(new X())...
f:
for(int i = 0; i < x.size() -1;)
{
X y = x.get(i);
for(int j = i + 1; j < x.size();)
{
if(a) {
x.remove(j);
continue;
}
if(b) {
x.remove(i);
continue f;
}
j++;
}
i++;
}

I don't think it will be unpredictable, but your style seems wrong to me, so your approach is suspect.
Using a label is a bad idea, and deciding to use it shows that your approach is flawed.
You may want to look at this discussion about deleting on ArrayList, but basically, LinkedList would be fsster:
http://www.velocityreviews.com/forums/t587893-best-way-to-loop-through-arraylist-and-remove-elements-on-the-way.html
But, removing this way will work.
UPDATE:
Oops, just saw a couple of bugs:
if(a) {
x.remove(j);
continue;
}
OK, in this one, you will go back through the loop for j, but you didn't increment j.
if(b) {
x.remove(i);
continue f;
}
This is the same for i.
So, you need a similar change to fix it:
for(int i = 0; i < x.size() -1; i++)
This way, when you hit continue then it will still go to the next element.

It would be better to create an array which contains indexes to remove.
And fill it with indexes in the main for cycle. Than you can do something like this:
Collections.sort(indexesToRemoveArr);
Collections.reverse(indexesToRemoveArr);
for (int indexToRemove : indexesToRemoveArr) {
arr.remove((int) indexToRemove );
}
In that code I remove indexes from end to start. That's why it won't do any problems.

Yes. Compiler will optimize and call x.size() only once. So your terminatin condition becomes incorrect as soon as you remove element.

Related

The code showing Time Limit Exceed erroe, could some one explain, where is problem in this code [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
LeetCode 485
Given a binary array nums, return the maximum number of consecutive 1's in the array.
Example 1:
Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
---------Solution:-------
public int findMaxConsecutiveOnes(int[] nums) {
int maxConsSize = Integer.MIN_VALUE;
int i = -1, j=-1, k=0;
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
return maxConsSize;
}
Warning: This is not direct answer (for this "do my homework" question)
You should use (or learn to use) debugger in your IDE (trust me, IDE, e.g. Eclipse will help you a lot in your beginnings).
The easiest (I'm not saying smartest) way, how to know what the program is doing (when you need to know, like in this case) is to add some print statements, e.g. add System.out.println("k=" + k) into your program (in a while loop).
You might want to watch this youtube video.
You have an infinity loop. Try run this:
public class Test {
public static void main(String[] args) {
int maxConsSize = Integer.MIN_VALUE;
int[] nums = {1,1,0,1,1,1};
int i = -1, j=-1, k=0;
System.out.println(nums.length);
while(k<nums.length){
while(k<nums.length && nums[k] == 1){
k++;
i++;
System.out.println("k = " + k);
}
if(nums[k] == 0){
maxConsSize = Math.max(maxConsSize,i-j);
j = i;
}
}
maxConsSize = Math.max(maxConsSize,i-j);
System.out.println(maxConsSize);
}
}
Output:
6
k = 1
k = 2
After reading the first 0 you are in infinite loop. You have made this task very complicated :)
It's probably not the best solution, but it should be faster
public int findMaxConsecutiveOnes(int[] nums) {
int maxCons = 0;
int currentCons = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
if (currentCons > maxCons) {
maxCons = currentCons;
}
currentCons = 0;
} else {
currentCons++;
}
}
if (currentCons > maxCons) {
maxCons = currentCons;
}
return maxCons;
}
}
There are two basic forms of loops:
for-each, for-i or sometimes called ranged for
Use that for a countable number of iterations.
For example having an array or collection to loop through.
while and do-while (like until-loops in other programming languages)
Use that for something that has a dynamic exit-condition. Bears the risk for infinite-loops!
Your issue: infinite loop
You used the second form of a while for a typical use-case of the first. When iterating over an array, you would be better to use any kind of for loop.
The second bears always the risk of infinite-loops, without having a proper exit-condition, or when the exit-condition is not fulfilled (logical bug). The first is risk-free in that regard.
Recommendation to solve
Would recommend to start with a for-i here:
// called for-i because the first iterator-variable is usually i
for(int i=0; i < nums.length, i++) {
// do something with num[i]
System.out.println(num[i]):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no counting, etc. inside the loop-body
Even simpler and idiomatic pattern is actually to use a for each:
for(int n : nums) {
// do something with n
System.out.println(n):
}
because:
it is safer, no risk of infinite-loop
the iterations can be recognized from the first line (better readability)
no index required, suitable for arrays or lists
no counting at all
See also:
Java For Loop, For-Each Loop, While, Do-While Loop (ULTIMATE GUIDE), an in-depth tutorial covering all about loops in Java, including concepts, terminology, examples, risks

JAVA for loop: all except a specified number

I need this for an array, but basically the idea is that a for loop will run, and whatever number you tell it to skip, it won't do. So for(int x=0; x<50; x++) if I want 1-50 except 22, how would I write that?
This would give me the ability to skip a certain number in my array.
Sorry if this is an extremely simple question, I am not too familiar with Java.
Make use of continue, something like this:
for(int x=0; x<50; x++) {
if(x == 22)
continue;
// do work
}
Suggested reading: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
public static final void doSkippedIteration(final int[] pArray, final int pSkipIndex) {
for(int i = 0; i < pSkipindex; i++) {
// Do something.
}
for(int i = pSkipIndex + 1; i < pArray.length; i++) {
// Do something.
}
}
You would have to do some basic check to see whether pIndex lies within the confines of the array. This saves you from having to perform a check for every single iteration, but does require you to duplicate your code in this specific example. You could of course avoid this by wrapping the code in a wider control block which handles the two iterations in a cleaner manner.

Why are variable not recognised from inside for-statements?

What I am trying to do is create an array that pulls even numbers from another array. I'm not sure if I have gone about it the right way. I've look for ways of returning from statements like you would functions/methods and I can't find anything, not even sure if it is possible.
Anyway, the issue I am having here is the 'return evenArray' below 'cannot find symbol.' I am not sure what this means?
public static int[] getEvenArray(int[] array)
{
int dividedBy = 2;
int evenElement;
int evenCount = 0;
for(int i = 0; i < array.length; i++)
{
int[] evenArray;
evenElement = array[i] % dividedBy;
if(evenElement == 0)
{
evenCount++;
}
else
{
array[i] = 0;
}
evenArray = new int[evenCount];
for(int x = 0; x < evenArray.length; x++)
{
if(array[i] != 0)
{
evenArray[x] = array[i];
}
}
}
return evenArray;
}
This is for a tutorial from one of my lectures, it's a little bit challenging to say the least :-)0
evenArray is defined within the scope of the for loop. (Actually a little worse than that; you're redeclaring it on each iteration so discarding the previous contents).
So once you're outside the for loop you can't refer to it.
Quickest fix is to use a std::vector<int> for this type, and declare it at the start of the function. Also change the return type of the function to the same. Don't forget to size the vector appropriately.
(Moving on, a smart lecturer will ask you about returning a std::vector which could potentially take a deep copy of that vector. Pre C++11 you'd mention return value optimisation, now you can talk about r-value references. No deep copy will be taken since the move constructor will be used).
Variable declared inside a block is not visible outside of it; move this int[] evenArray; to very start of function.

Array search code

In the book 'Data structures and algorithms in java' the following Array search method code is provided:
{
int j;
for(j=0; j< nElems; j++) // for each element,
if( a[j].getLast().equals(searchName)) // found item?
break; // exit loop before end
if(j == nElems) // gone to end?
return null; // yes, can't find it
else
return a[j]; // no, found it
}
I am trying to understand why there needs to be a if(j == nElems) check? Wouldn't the method work the same if it were written as:
{
int j;
for(j=0; j <nElems; j++)
if( a[j].getLast().equals(searchName))
return a[j];
return null;
}
it would :P You could declare the j inside the for to limit its scope as well.
In the first implementation what it do is check if it iterated over all elements and didn't find anything, because j was incremented until it is equal the the condition of stop of the for-loop. I.e., it didn't stop because of break, indicating that it found an element.
I prefer your solution because it's easier to read :)
Yes, both of these ways are give the same result.
Well , j never equals to nElems so this condition (j==nElems) is not wrong BUT it's not Working .
You can make it like this (j==nElems-1) but it's steal waste of code , So your algorithm is better than the first one .

iterator for loops with break

let say my code look like below
for(..)
for(..)
for(..){
break; //this will break out from the most inner loop OR all 3 iterated loops?
}
Your example will break out of the innermost loop only. However, using a labeled break statement, you can do this:
outer:
for(..)
for(..)
for(..){
break outer; //this will break out from all three loops
}
This will only break out from the inner loop. You can also define a scope to break out from. More from the language specs:
A break statement with no label
attempts to transfer control to the
innermost enclosing switch, while, do,
or for statement of the immediately
enclosing method or initializer block;
this statement, which is called the
break target, then immediately
completes normally.
Yes, without labels it will break only the most inner loop.
Instead of using labels you can put your loops in a seperated function and return from the function.
class Loop {
public void loopForXx() {
untilXx();
}
private void untilXx() {
for()
for()
for()
if(xx)
return;
}
}
From the most inner loop :)
int i,j,k;
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
for(k = 0; k < 2; k++)
{
printf("%d %d %d\n", i, j, k);
break;
}
Will produce :
0 0 0
0 1 0
1 0 0
1 1 0
You should take a look here: http://java.sun.com/docs/books/tutorial/java/nutsandbolts/branch.html
as often mentioned i don't like to break with a label eather. so while in a for loop most of the time i'm adding a boolean varible to simple exit the loop.. (only if i want to break it of cause;))
boolean exit = false;
for (int i = 0; i < 10 && !exit; i++) {
for (int j = 0; j < 10 && !exit; j++) {
exit = true;
}
}
this is in my opinion more elegant than a break..
Many people here don't like labels and breaking. This technique can be compared to using a 'goto' statement, a flow control statement which allows jumping out of a block of code in a non-standard way, obliviating use of pre- and post conditions. Edsger Dijkstra published a famous article in Communications of the ACM, march 1968, 'Goto statement considered harmful' (it's a short read).
Using the same reasoning presented in the article, returning from inside an iteration as suggested by TimW is also bad practice. If one is strict, to create readable code, with predictable entry- and exit points, one should initialize the variable which will hold the return value (if any) at the beginning of the method and return only at the end of a mehod.
This poses a challenge when using an iteration to perform a lookup. To avoid using break or return one inevitably ends up with a while-loop with a regular stop condition and some boolean variable to indicate that the lookup has succeeded:
boolean targetFound = false;
int i = 0;
while (i < values.size() && ! targetFound ) {
if (values.get(i).equals(targetValue)) {
targetFound = true;
}
}
if (!targetFound) {
// handle lookup failure
}
Ok, this works, but it seems a bit clunky to me. First of all I have to introduce a boolean to detect lookup success. Secondly I have to explicitly check targetFound after the loop to handle lookup failure.
I sometimes use this solution, which I think is more concise and readable:
lookup: {
for(Value value : values) {
if (value.equals(targetValue)) {
break lookup;
}
}
// handle lookup failure here
}
I think breaking (no pun intended) the rule here results in better code.
it will breake from most inner loop,
if you want to break from all, you can hold a variable and change its value when you want to break, then control it at the beginning of each for loop

Categories