I have a recursive method that i would like to return a value from when a specific if statement returns true (which it always does)
if (compactArray != null) {
if (arrayCount == (compactArray[0].length - 1)) {
return compactArray;//i want to return here
}
}
But Java wont let me return from the if, and throws a warning that i need to add a return value.
What does one do? The full method is as follows
public String[][] diXmlRecursiveRead(Iterator<Element> list, String[] columnNames, String[][] compactArray,
Integer arrayCount) {
Element element = null;
String[] columns = null;
while (list.hasNext()) {
element = list.next();
// Assign data to the two dimensional array, starting from position
// 1 in the length to not overwrite the column names.
// This is also where i would print the column name plus its
// attribute value if i was printing to console.
if (columnNames != null) {
for (int a = 0; a < columnNames.length; a++) {
compactArray[a][arrayCount] = element.getAttributeValue(columnNames[a]);
}
}
// Find the element that contains the columns="" information
if (element.getAttributeValue("columns") != null) {
// reset the array count, since we are processing a new
// columns="" section
arrayCount = 1;
columns = element.getAttributeValue("columns").toString().split(",");
// set width size +1 to make room for the column names
// (columnNames + data +1)
compactArray = new String[columns.length][element.getChildren().size() + 1];
// Set the EVE column names in the first column of the two
// dimensional array
for (int a = 0; a < columns.length; a++) {
compactArray[a][0] = columns[a];
}
}
// After added the last value to the two dimensional array return the
// array[][]
if (compactArray != null) {
if (arrayCount == (compactArray[0].length - 1)) {
return compactArray;//i want to return here and not at the end!
}
}
// Method calls itself with a new level of the child
diXmlRecursiveRead(element.getChildren().iterator(), columns, compactArray, arrayCount++);
}
//Java want me to return here!!
}
look at that example:
static int count = 0;
private static boolean foo() {
if (count == 5) {
return true;
}
count ++;
return foo();
}
note that the recursive call is called with the 'return' statement.
Think about the stack that is being build when you execute a recursive method. at some point all methods need to start returning a value up the stack.
You need to pass through the String[][] compactArray parameter and return that. This is the result of your method that will be returned at the end.
Returning starts when the deepest level of recursion is done. Then everything is passed through till the first call of your method.
Added some code:
package recursion;
import java.util.Iterator;
import java.util.LinkedList;
import javax.xml.bind.Element;
class Recursionat0r {
static private int threshhold = 3;
public static void main(String[] grmlZ) {
Recursionat0r recursionat0r = new Recursionat0r();
String[] columnNames = { "hello", "world" };
String[][] compactArray = new String[4][10]; // would recommend
// ArrayList here
compactArray = recursionat0r.diXmlRecursiveRead(null, columnNames, compactArray, 0);
recursionat0r.printCompactArray(compactArray);
}
public String[][] diXmlRecursiveRead(Iterator<Element> list, String[] columnNames, String[][] compactArray,
Integer arrayCount) {
String[] columns = columnNames;
// append stuff to array
// compactArray[a][arrayCount] =
compactArray[arrayCount] = columnNames;
// Method calls itself with a new level of the child
// this is a _recursion step_
// OR
// Method returns the compactArray!
// this is the _recursion ancor_
if (arrayCount < threshhold) {
System.out.println("returning diXmlRecursiveRead");
return diXmlRecursiveRead(null, columns, compactArray, ++arrayCount);//increment arrayCount BEFORE passing ;) - else it gives stackoverflow (haha)
// Java want me to return here!!
} else {
System.out.println("returning the compactArray");
// _recursion anchor_
return compactArray; // this marks the end of the recursion
// values start to be passed back from here
// you might want to specify another condition for the anchor to be
// thrown ;)
}
}
public void printCompactArray(String[][] compactArray){
for(int count = 0; count < compactArray.length; count++){
for(int inside=0; inside < compactArray[0].length; inside++) //warning assuming all Arrays in compactArray have the same length
System.out.println(compactArray[count][inside]);
}
}
}
This yields:
returning diXmlRecursiveRead
returning diXmlRecursiveRead
returning diXmlRecursiveRead
returning the compactArray
hello
world
hello
world
hello
world
hello
world
Hope this helps ^^-d
I think you may need to add a default return value to your method.
The compiler needs to know wich value to return when your 'if' test fails.
You could just add a return value at the end, just to make the compiler relax. This happens because, if the "if" clause is false, then you return nothing from this function. I guess this is a base case return, right?
Change:
// Method calls itself with a new level of the child
diXmlRecursiveRead(element.getChildren().iterator(), columns, compactArray, arrayCount++);
to
// Method calls itself with a new level of the child
return diXmlRecursiveRead(element.getChildren().iterator(), columns, compactArray, arrayCount++);
Note the added return di....
If a method returns a value then ALL routes through the code must return something. In your case only the deepest level of recursion will return something. All the others would just throw away the value discovered.
Related
I want to count all the objects that are true and return it (as I have tried to do in countNational. The method I use to assign an object as true/false is in a different class and named NationalMessage. I have pasted it below the main method.
public class Ex6
{
public static int countNational (ArrayList<Message> messageList)
{
int countTrue = 0; //will count those that are true
for (int i = 0; i<= messageList.size(); i++)
{
if(messageList.get(i)==true) //GETTING ERROR SAYING CAN'T COMPARE BOOLEAN
countTrue = countTrue + 1;
}
return countTrue;
}
public static void main(String[] args)
{
ArrayList<Message> messageList = new ArrayList<Message>();
messageList.add(new NationalMessage("UKJohn","UKMark","aa"));
messageList.add(new NationalMessage("UKJohn","FRJean","aa"));
messageList.add(new Message("Mike","John","aa"));
System.out.println(countNational(messageList));
}
}
************************* THE BELOW IS A METHOD FROM A SEPERATE CLASS CALLED NATIONAL MESSAGE*****************************
public NationalMessage(String ssender, String rreceiver, String ccontent)
{
super(ssender,rreceiver,ccontent);
if (ssender.equals("UK") && rreceiver.equals("UK"))
{
isNational = true;
}
else
{
isNational = false;
}
}
using a stream in java8 is jsut as simple as filtering the list
long xx = myList.stream().filter(t -> t.isNational).collect(Collectors.counting());
or to get the list
List<NationalMessage> x = myList.stream().filter(t->t.isNational).collect(Collectors.toList());
Change:
if(messageList.get(i)==true)
to:
if(messageList.get(i).isNational==true)
Why?
Because you can compare apples with apples and oranges with oranges.
On right hand side of == , true is present. So on left hand side also there should be a boolean or an expression that results in a boolean.
Your original expression messageList.get(i) does not result in a boolean. Rather it results in an object or null.
In some languages like C, a null may be interpreted as false and non-null may be interpreted as true but in Java, it's not so.
You have to be explicit about the booleans.
For e.g. left hand side expression in your case could be :
messageList.get(i)!=null which would evaluate to true/false
I am trying the following code for heap sort which is giving ArrayIndexOutOfBoundsException exception:
package com.Sorting;
import java.util.Arrays;
public class HeapSort {
private static int arr[];
private static int l,r,max,hsize;
/**
* #param args
*/
public static void main(String[] args) {
int []numbers={55,2,93,1,23,10,66,12,7,54,3};
System.out.println(Arrays.toString(numbers));
HeapSort(numbers);
System.out.println(Arrays.toString(numbers));
}
private static void HeapSort(int myarr[]) {
// TODO Auto-generated method stub
arr = myarr;
hsize = arr.length - 1;
BuildHeap(arr);
for(int i = hsize;i>0;i--)
{
swap(0,i);
hsize--;
SatisfyHeap(arr,0);
}
}
private static void BuildHeap(int[] arr) {
// TODO Auto-generated method stub
for(int i = hsize/2; i>=0;i--)
{
SatisfyHeap(arr, i);
}
}
private static void SatisfyHeap(int[] arr, int i) {
// TODO Auto-generated method stub
l = 2*i;
r = 2*i+1;
if(l<=hsize && arr[l]>arr[i])
// if(arr[l]>arr[i] && l<=hsize )
{
max = l;
}
else
max = i;
if(r<=hsize && arr[r]>arr[max])
{
max = r;
}
if(max!=i)
{
swap(i,max);
SatisfyHeap(arr, max);
}
}
private static void swap(int i, int max) {
// TODO Auto-generated method stub
int temp = arr[i];
arr[i] = arr[max];
arr[max] = temp;
}
}
The above code does not give any error if I just swap the expressions used on the left hand side and right hand side in the if statement of SatisfyHeap method. i.e. you can try commenting the third line of the SatisfyHeap method and uncomment the fourth line. Please help to understand this magic.
Short answer
The magic is called "short-circuit evaluation" and it was designed speciifcally for the cases like this.
Longer answer
In Java and many other languages logicallly code
if (condition1 && condition2) {
do something
}
is equivalent to
if (condition1) {
if (condition2) {
do something
}
}
By "equivalent" here I mean that if condition2 is something to be computed it will not be computed if condition1 happens to be false. Also this is correct from the boolean logic point of view. This trick is useful in two respects. First, it improves performance by skipping evaluation calculation2. Secondly, it is useful in cases such as yours were condition1 is a "guard condition" for condition2.
Another example is function isEmptyString that is implemented by many Java-developers in a following way
public static boolean isEmptyString(String s) {
return (string == null) || (string.length() == 0);
}
Without short-circuting logic, this expression would raise a NullPointerException if s happens to be null.
Your specific case (Why ArrayIndexOutOfBoundsException at all?)
Another point of your question might be "How it happens that there is ArrayIndexOutOfBoundsException at all?". To answer this question consider the case when the very first element is actually the largest in the heap and we should move it down to the last layer of the tree. This movement down is implemented by your SatisfyHeap. So now assume that we did last swap that moved the biggest element to the bottom. Now as max was changed we'll do one more recursive call and in that call i > arr.length / 2 so l = 2*i > arr.length and thus the exception happens.
Side-note, I'd say that unless you pre-allocate arr to be bigger than actual heap size storing hsize independently from arr.length is a bad idea that makes code harder to understand.
Following gives you an error
if(arr[l]>arr[i] && l<=hsize )
because l is greater than the size of the array and you are trying to get the array element by passing l which is out of array's bounds.
Following works for you
if(l<=hsize && arr[l]>arr[i])
because in the if condition, the first thing that is evaluated is the expression l<=hsize. Since l is greater than hsize, the expression evaluates to false. Since the two clauses of your if predicate are joined with an && operator, as per the short circuiting rules, the expression in the second clause is not even evaluated saving you from accessing the array with an out of bound index. Therefore you don't get any error.
I have this method that adds temp to xy array.
public void printBoard(int temp[][],int type){
if(type == 1) {
xyArray.add(new Array(temp));
numberOfSolutionsXY++;
}
}
xyArray is global and declared as
public ArrayList<Array> xyArray = new ArrayList();
When I check its value before exiting the method printBoard, it prints the expected 2d array. But when I go to another method, the value of xyArray is different. It has the value of the other Arraylist.
I checked back and forth many times, I did not just mistype the parameter. It's not happening only on xyArray, the same happens to other arraylists: regArray, xArray and yArray
This is how I check the value
System.out.println("\n xy \n"+xyArray.toString());
I do solveBoard method and tries to add the expected value of arrays but different values were appended. They were all the same.
problemArray.add(new Array(board));
solveBoard(board,0,0,4);
if(numberOfSolutions>0)
solutionArray.add(new ArrayList(regularArray));
solveBoard(board,0,0,3);
if(numberOfSolutionsX>0)
solutionArray.add(new ArrayList(xArray));
if(dimension%2==1){
solveBoard(board,0,0,2);
if(numberOfSolutionsY>0)
solutionArray.add(new ArrayList(yArray));
solveBoard(board,0,0,1);
if(numberOfSolutionsXY>0)
solutionArray.add(new ArrayList(xyArray));
}
solutionsArray.add(new ArrayList(solutionArray));
System.out.println("\nsolutions\n"+regularArray.toString());
All of them have the value of problemArray. Even though i placed problemArray.add(new Array(board)); at the bottom, they still get its value.
This is the class Array i've made
public class Array {
int[][] array;
public Array(int[][] initialArray){
array = initialArray;
}
public String toString(){
String x = "";
for(int i = 0;i<array[0].length;i++){
for(int j = 0;j<array[0].length;j++)
x+=array[i][j];
x+="\n";
}
return x;
}
}
Full code here
Try to rename your "Array" class, for example to "MyArray"
And i suppose there are some troubles with Array class constructor.
Try to copy initialArray in to your local variable.
public class MyArray {
int[][] localArray;
public MyArray(int[][] initialArray) {
localArray = initialArray.clone();
for (int i = 0; i < initialArray.length; i++) {
localArray[i] = initialArray[i].clone();
}
}
public String toString() {
// ...
}
}
I am passing few values to mail method for sending the details like below
private static String getTeam(String Team, List<String> prioritys1, String number,String description
) {
StringBuilder builder1 = new StringBuilder();
for (String v : prioritys1) {
if ( v == "1") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
else
if ( v == "3") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
}
return builder1.toString();
}
I tried to store in arrays but it didnt worked.
I after pass above parameters, i need to store the value of the number. i need to store the number so that next time while passing the parameters i need to check first whether the number is already passed or not if not then only i need to pass to mail.
can any one help on this
With this code very complicated understand what you are doing. But if you need check value that already been processed store it outside of the method. Create global class variable:
public class className {
private final List<String> ARRAY = new ArrayList<>(); // global variable
public void yourMethod(String value) {
if (!ARRAY.contains(value)) {
mail(value);
ARRAY.add(value);
}
}
}
I dont know your case and I can not get better example.
You need to store the value in a "class level" variable. Whether the variable type needs to be static or instance will depend on your implementation of the method.
If you can post a sample code, we can help further.
You need to compare with 2 equals and not 1
Instead of
if( Team = A )
you need this way
if( Team == A )
Using Team = A, your saying that every time your code reaches that line it will equal Team to A.
I'm new to using OOP, I typically just put all my code in a single class and use methods. But I want to maintain state information and think classes are the best fit but I'm having trouble wrapping my head around it.
Say I have a list of items and I want to stop when the total sum of all previous items in the list equals X(in this case 10 so it takes item 1 + 2, then 2+3.etc..until it hits the threshold 10), I can use a method to calculate it but it involves me doing the entire process all over again when all I really need to do is increment by the last item and then see if my data exceeds the threshold. Here's my code so far but I know its not good because although it works its really just using the class as an independent method and recalculating on every loop. My goal is to,using this structure, reduce loops if not necessary to check thresholds.
Any suggestions?
Code:
public class LearningClassesCounter {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data(current_location));
for (int i =0; i<100; i++){
if (checker.check_data(current_location) == false) {
break;
}
data_list[current_location] = (list[current_location]+1); //this is just a random function, it could be any math function I just put it in here to show that some work is being done.
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int[] data_list;
private int total_so_far;
// create a new counter with the given parameters
public Counter(int[] data_list) {
this.data_list = data_list;
this.total_so_far = 0;
}
public boolean check_data(int current_location) {
// TODO Auto-generated method stub
int total_so_far = 0;
//System.out.println(total_so_far);
for (int item : data_list) {
total_so_far = item + total_so_far;
if (total_so_far >= 10) {
break;
}
}
if (total_so_far>=10) {
return false;
} else {
return true;
}
}
}
I don't need anyone to fix my code or anything(I want to do it myself, the code is just to give an idea of what I'm doing). I'm more interested in the flaw in my logic and maybe a way for me to better think about designing classes so I can apply them to my own situations better.
So the solution is that you do not update the data_list directly. Instead have a setter method in the Counter class that takes the index and value to update. It updates the value in the array and also updates a count value.
Something like this:
class Counter{
private final int[] list;
private count = 0;
private final maxCount = 10;
public Counter(int[] list){
this.list = list;
}
public boolean updateValueAndCheckPastMax(int index, int value){
list[index] = value;
count += value;
return count >= maxCount;
}
}
You are way over thinking this, and a counter class is not really necessary in this case.
I'm also interested as to why you'd be doing this line:
data_list[current_location] = (list[current_location]+1);
Do you want your data_list to be the same as list, but each value is incremented by 1?
If you are merely trying to return a sub-array of the values that are < 10, i would suggest just doing this in a for loop, and using an int as a counter.