How can I refactor a `for` loop? - java

Problem
I want to be able to split up a for loop into a method, then put the for the method in the for loop to make it easier to read. Below demonstrates this:
Example.java
for(int member = firstMember; member < arrayOfMembers.length; member++) {
[...] other code
}
Should be refactored to:
Solution Example:
private boolean eachMemberInList() {
return int member = firstMember; member < arrayOfMembers.length; member++);
}
public static void main(String[] args) {
for(eachMemberInList());
}
Is this possible?

No, you cannot return or otherwise manipulate a for loop as if it were an object in Java.
However, what you're attempting to do is unnecessary. You can use an array directly in an "enhanced" for loop, since Java 1.5.
for (int member : arrayOfMembers) { ... }
It is more concise than attempting to create a method to manipulate a for loop, and it is even more concise than the standard for loop you're attempting to replace.

What you're talking about is turning a for loop, into a while loop.
for (; true; )
is equivalent to
while (true)
So, you're solution could be viewed as
while (someFunctionIsTrue()) {}
Don't want to get into religious debates here, but generally, if you're iterating over an array of objects, you really do want to use a for lop. Not necessarily because it's any different than a while loop using your solution, but because it's idiomatic. When a developer (an experienced developer) sees a for loop, the fact that you chose a for loop tells them something. It says, hey, I'm iterating over the objects of a container. What a while loop says, is that there is some condition, and while that condition is true do something.
While loops and for loops are identically in capability. By using them idiomatically, you can communicate your code more concisely and clearly. For example:
int index = 0;
while (index < array.size) {
doSomethingWithArrayElement(array[index]);
index++;
}
This is not concise. The hanging variable declaration creates an extra line of code, as does the index++ at the end. When you do this:
for(int i = 0; i < array.size; i++) {
doSomething(array[i]);
}
This is very concise, and your use of a for loop... if used concistently like this, immediately tells a developer that all items of this container are going to have something done with them!
Now let's use the alternate example, where we have a function that returns a boolean. And this boolean tells the loop whether to continue or not. We could do something like this:
int index = 0;
for (; doSomethingWithArrayItem(array, index); index++){
}
boolean doSomethingWithArrayItem(array, index) {
//blah blah blah
if (index + 1 == array.size) return false;
return true;
}
This accomplishes what you want, but is difficult logic to follow. Let's say that you named your doSomething function something useful, like
incrementValueByTwo(item);
What do you think this function does? It's pretty clear right. Now, let's place this function in the for loop above:
int index = 0;
for (; incrementValueByTwo(array, index); index++){
}
How many values are we incrementing? Are we incrementing all the values of the array by 2? Some of them? The first one? Or perhaps none of them under certain circumstances? THIS IS VERY CONFUSING!!!! DON'T DO THIS!

I would rather do something like
String[] array = new String[10];
for(String variable : array){
doSomething(variable);
}
Or if you are using Java 8 then
Arrays.stream(array).forEach(memberOfArray -> doSomething(memberOfArray));
This is much more readable.

Related

Another way to compare two values of an array List to find the lonely integer in Java?

The problem to solve is to find a non-repeating integer in an Integer list. I used a while loop to compare each value with another. The function, however, returns the wrong value. This is a Hackerrank challenge which can be found here .
public static int lonelyinteger(List<Integer> a) {
int lonelyInt = 0;
for (int i = 0; i < a.size(); i++) {
for (int j=1;j<a.size();j++){
while (a.get(i)!=a.get(j)){
lonelyInt+=a.get(i);
}
}
}
return lonelyInt;
}
I would really appreciate any hints and/or more straightforward solutions. I am new to Java and practicing my skills.
Your approach of comparing each number with all the other numbers is correct in principle.
If we compare the ith element of the array with all the other elements, and none are equal to it, then we know it is the unique number.
Your program is not doing this correctly.
Think of the loops like this:
The outer loop using the index i is giving us the number we are checking for loneliness, a.get(i).
The inner loop using the index j is giving us each number to check against the current candidate selected by the outer loop, a.get(j).
So for each iteration of the outer loop we will need to keep track of whether any iteration of the inner loop matched. We could use a local boolean named equalNumberFound, which we set to false at the start of each iteration of the outer loop.
In the inner loop, we check whether we've found an equal number, and if we have, set it to true. Make sure that you don't check a number against itself!
At the end of each iteration of the outer loop, we check equalNumberFound, and if it's still false we can return the current outer loop number, because we now know that no other number was equal.
You need to review what you know about while loops, as it seems you have some incorrect assumptions about how they behave.
One of the ways you could approach the problem is by sorting the list first then compare each element to its adjacent element since the elements are limited to occurring either once or twice. Since only one element occurs once, then the element without an identical adjacent element is the stop condition. This approach achieves O(log(N)) time complexity and O(1) space complexity.
public static int lonelyInteger(List<Integer> a) {
Collections.sort(a);
for (int i = 1; i < a.size(); i += 2) {
if (a.get(i - 1).intValue() != a.get(i).intValue()) return a.get(i - 1);
}
return a.get(a.size()-1);
}
You can make use of hashset. Iterate through the list of integers:
Add element to hashset, if integer is not present in the hashset.
Remove the integer element, if it is already present in the hashset
Now return the lone non-repeating integer in the hashset.
public static int lonelyinteger(List<Integer> a) {
Set<Integer> set = new HashSet<>();
for (int n : a) {
if (set.contains(n)) {
set.remove(n);
} else {
set.add(n);
}
}
return set.stream().findFirst().get();
}
A better solution without using Streams
public static int lonelyinteger(List<Integer> a) {
Set<Integer> s = new HashSet<>();
for (int num : a) {
if(!s.add(num)){
s.remove(num);
}
}
return new ArrayList<>(s).get(0);
}

What it means ''depth()'' in java?

I am in a book with this code. I do not know which command the ''depth'' word is used for what purpose. I have found a few results but I do not understand what is still. I know java language but i am learning c ++ new.I wanted to know if there is something like this in Java.
if (depth() != otherStack.depth())
{
return false;
}
else
{
for (int n=0; n<depth(); n++)
{
if (!list[n].equals(otherStack.list[n]))
return false;
}
}
From the code snippet you posted, depth seems to be a method defined in the class whose instance is the otherStack variable. Here depth() probably returns the size of the stack.
The line depth() != otherStack.depth() compares the size of the Stack instance to the size of another Stack instance.

Having trouble understanding return type placement( Big Java Ex 6.8)

Currently on the chapter in my book where we talk about for loops and loops. I have sometimes come across an issue where the method needs me to return something. For example consider my code
below. Basically the exercise is to get all the factors in ascending order. Now heres the issue
As you can see I need a return statement outside of the for loop. Now I guess my book didn't exactly explain this properly, or I didn't understand the concept
of return properly in java, but does our return statement always have to be in the most outer indentation if you will?
The thing is, I don't really want to return anything outside of the for loop. I just want to return i upon that condition. Why doesn't java let me do this?
Whats a good counter-action?
Ever since I started learning loops and for loops, I have been having trouble understanding this. I guess I could just system.out.println(i) instead of returning it? But then what should I return? I could also make it a void type, and then make another method to print it, I guess?
class factors{
private int num;
public factors(int num)
{
this.num = num;
}
public int getFactors()
{
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
return i;
}
}
// I NEED TO PUT A RETURN STATEMENT HERE
}
}
public class test{
public static void main(String [] args)
{
factors fact = new factors(20);
System.out.println(fact.getFactors());
}
}
IT WORKS NOW ( I dont particularly like my solution)
class factors{
private int num;
public factors(int num)
{
this.num = num;
}
public void getFactors()
{
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
System.out.println(i);
}
}
}
}
public class test{
public static void main(String [] args)
{
factors fact = new factors(20);
fact.getFactors();
}
}
The thing is, I don't really want to return anything outside of the for loop. I just want to return i upon that condition. Why doesn't java let me do this?
Java lets you do that. There is nothing wrong with returning inside the loop upon reaching the condition.
Java allows you to have multiple return statements, so adding another return 0; after the loop is allowed.
Java returns once it hits the first return statement, and other return statements are not executed (the method isn't executed anymore) (except for some rare edge cases with try-catch and return, but thats another story entirely).
But why is it required?
Java requires that for all possible paths there exists a return with the proper type. Even if you yourself can proof mathematically that the path Java complains about is never taken, the compiler might not be able to prove that the path is not possible at runtime. So you simply need to add an return there with a dummy value.
In your concrete example, there is a condition in which the loop gets never executed. If num <= 0, then the loop condition is never satified and the entire loop body is skipped. Without the return,the method is invalid, because you can't return nothing from an method with return type int.
So, in your example, the compiler is actually smarter then you, and prevents you from making a mistake - because it found the path you thought wouldn't occur.
new factors(-1).getFactors(); // you don't check the passed value at all ;)
From your comments, it seems that you want to return all factors. In java, you return once, and only once, from a function. This means you have to aggregate the results and return a List or array of values:
public List<Integer> getFactors(int num) {
List<Integer> factors = new ArrayList<>();
for (int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
factors.add(i);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(new factors(20).getFactors());
// prints a comma-separated list of all factors
}
does our return statement always have to be in the most outer indentation if you will?
No.
However, all potential code paths must return something. Consider this structure:
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
return i;
}
}
What happens if num is a value where the loop itself is never entered? Or what happens if the if condition is never satisfied? No return statement would ever be encountered, which is invalid.
The compiler has to guarantee that the method will return something, under any and all potential runtime conditions. So while it's perfectly valid to return from within the loop, you also must provide logic for what to return if that return statement is never reached.
Java doesn't let you do that because what happens if the if (num % i == 0) is never true?
The methods return type is int, so it has to return an int. And it's possible that the if statement could be false, not every condition is covered with a return statement.
So if you wanted to you could return something like -1, or another invalid value. Then you know that the function didn't find what it was looking for.

Does not return the index of the student, always returns -1 (Array)

I am learning java for the first time because of my interest in programming and there is a problem with this program I am working on.
This code is meant to return the index of an agent in question or -1 if not found but it keeps returning -1.
private Agent [] agents; //an array of Agent
public int findAgentLocation (String name)
{
for (int index = 0; index < agents.length; index++)
{
if (agents[index]).equals(name)){
return index;
}
}
return -1;
}
}
Thank you for your kind help
When you do this: if (agents[index].equals(name)){ , you are essentially comparing two different datatypes ('Agent' and 'String'). Java will do an object comparison and hence they will never be equal. So you end up getting back "-1" always.
Assuming Agent class has a name variable, You'll need to do something like this:
if (agents[index].getName().equals(name)){
You may want to check your equals(String) in Agent

Java, Create array if it doesn't already exist

I couldn't find anything on that while googling
so
I want to create an array only if it doesn't already exists.
EDIT: I mean not initialized
I know how to check for values in the array
Should be simple but I'm stuck
best regards
static long f(long n) {
int m = (int)n;
**if (serie == null) {
long[] serie = new long[40];
}**
if (n == 0) {
return 0;
}
else if (n==1) {
return 1;
}
else {
long asdf = f(n-1)- 2*(f(n-2)) + n;
return asdf;
}
}
something like that
a recursive function and I want to save the values in an array
You are trying to use the serie array but it is not yet declared. First declare it and then use it, as you want.
Are you looking for:
if (values == null)
{
values = new int[10];
}
or something like that? If not, please edit your question to provide more information.
EDIT: Okay, judging by the updated question, I suspect you ought to have two methods:
static long f(long n)
{
return f(n, new long[40]);
}
static long f(long n, long[] serie)
{
// Code as before, but when you recurse, pass in serie as well
}
(Note that your current code doesn't use serie at all.)
if(array==null){
//create new array
}
AFAIK, there are, if you use a variable in java, it is initialized. So you probably want to check if that variable, an array in this case, is null. Not only that, you can and probably should check if it is an array. Arrays are objects in java. So you could do something like this for an array:
if(!obj.getClass().isArray())

Categories