When I pass an array as function parameter in Java, say:
public static void main(String... args){
int[] in=new int[]{57,40...23};
int[] post=new int[]{50,18...0};//arrays abbreviated for expediency
treeNode tree=buildTree(in, post);
print(tree);
}
public static treeNode buildTree(int[] in, int[] post)
{
int root_data= post[(post.length)-1];
int root_index=search(root_data, in);
treeNode root=new treeNode(root_data);
root.setLeft(buildTree(subArray(in, 0, root_index),subArray(post, 0, root_index)));
root.setRight(buildTree(subArray(in,root_index+1, in.length),
subArray(post,root_index, post.length-1)));
return root;
}
public static int[] subArray(int[] array, int start, int end)
{
int[] result=new int[end-start];
for(int i=0; i<end-start;i++)
{
result[i]=array[start+i];
}
return result;
}
public static int search(int key, int[] array)
{
for(int i=0; i<array.length; i++){
if(array[i]==key)
return key;
}
return array.length;
}
I get an arrayIndexOutOfBounds exception. Through the debugger I discovered that mysteriously the arrays became length 0. Why is this?
In your search() method you probably want to return i instead of key. Since you later use root_index variable (that you found with this function) as array index, that's where you might have troubles (arrayIndexOutOfBounds exception thrown). Even if root_index is within the range of array indices, its value is still wrong - to be exact, it's 0 in your example, and subArray() method returns empty array.
You might want to consider using standard tools instead of your own methods:
Arrays.sort() followed by Arrays.binarySearch() to search: even though asymptotically it's worse than your simple search - O(n*lon(n)) to sort plus O(log(n)) to binary search vs. O(n) in your case - considering you probably have small arrays this is still reasonable, but you get the guaranteed correctness of the algorithm
Arrays.copyOfRange() to copy range of array
Also, I don't see any definition of the treeNode class, but I guess you just omitted it in your posted code piece for the sake brevity.
A quick note on the style too: in Java, variables and methods are called using camelCase (so you might want to rename root_index into rootIndex and so on) and classes begin with the upper-case letter (so treeNode would better be named TreeNode). It will make your code more (intuitively) understandable to other people when they read it.
Hope that helps!
Related
I have this exercise:
public class Test2 {
public static void main (String [] args){
int index=1;
getArray()[index=2]++; //why???
}
public static int[] getArray() {
return null;
}
}
In my opinion, to call the static method getArray it is necessary to write:
getArray(); ... without the index!
I considered this code with a compiler error.
Can you explain me why getArray() [index =2]++; compiles without errors?
Let's go step by step:
the method is supposed to return an array of int (public static int[])
that array gets then accessed at index 2 (whateverArray [index=2])
finally, the result of that access (an int value) can be incremented (whateverArray[2]++)
and yes, a minor thing, you can assign a variable and use that as array index in the same statement, too
Thus this is all legal syntax. Of course, at runtime, you end up with a nullpointer exception.
The compiler could know that the method returns null, but standard javac does not care about such subtle details (for method results). And any decent IDE will tell you immediately that this code will break when executed.
Hi and thanks for noticing my problem. I want to write a method that can be used by different types of arrays. But my code always looks like this:
public int indexOf_1(int[] a,int b){
//Find the first matched result and return, otherwise report -1
int index = -1;
for(int j=0;j<a.length;j++){
if (a[j]==b)
{index=j;}
}
return index;
}
public int indexOfChar_1(char[] a,int b){
//Consider merged to the previous method?
int index = -1;
for(int j=0;j<a.length;j++){
if (a[j]==b)
{index=j;}
}
return index;
}
That seems to be redundant and I'm completely uncomfortable with such code duplication. Is there any way to write a searching method for all kinds of array to avoid repeating in this case? Thanks!
Unfortunately because the way arrays and the JVM work, this can't be reduced. Not even generics can help since int[] cannot be safely cast to Object[] without explicit conversion.
This looks like a common util function. If you're not comfortable with the code duplication, you can consider using one of the many libraries which provide this functionality. Guava and Commons-Lang are a few.
Guava puts them in the class relevant to the primitive type. Commons-Lang arranges them in the ArrayUtils class
e.g.
Bytes.indexOf(byteArray, (byte) 2);
Ints.indexOf(intArray, 22);
ArrayUtils.indexOf(intArray, 6);
Well you could use Object[] but you might not want to use ==, since it will compare identity of objects instead of values, instead you probably want to use .equals(). (Unless you know the value will always be a char or int) Perhaps this:
public int indexOf(Object[] a, int b) {
int index = -1;
for (int j = 0; j < a.length; j++) {
if (a[j].equals(b)) {
index = j;
}
}
return index;
}
public static <T> int index_Of(Object[] input,T value){
//Find the first matched result and return, otherwise report -1
for(int j=0;j<input.length;j++){
if(input[j].equals(value))
return j;
}
return -1;
}
You can generalize you method to deal with all kind of arrays. However, please pay more attention to the type. If you want to use Object referring to primitive type, when declaring a primitive type array, you need to use reference type. For example,
Character [] a = new Character[]{'a','b','c'};
DO NOT use char, since it will compile error when type checking.
The following code:
public static void main(String[] args) {
int first = 1;
int second = 2;
sum(first,second);
System.out.println(sum);
}
public static int sum(int a, int b){
int sum = a+b;
return sum;
}}
will return error and I need to write
int x = sum(first,second);
System.out.println(sum);
and define that method as integer x and print x.
But for array,
public static ArrayList<String> removeLast(ArrayList<String> list) {
//code
return list;
}
public static void main(String[] args) {
//code
removeLast(persons);
System.out.println(persons);
}
will print the returned value of array without defining as another array as the was with the previous one.
I am sorry if the question has already been asked as I couldn't find it. And I am just learning Java.
Arrays are passed by (value of) reference, therefore, any change that happens to the array inside the method, will actually change the array passed in to it. On the other hand ints are passed by value. Change an int inside a method, and it won't change the int passed into the method.
For this reason, the return statement in your array method is completely unnecessary. Your code will still change the array, even if you omit the return statement.
But there's another misconception that needs to be pointed out: when you sum two ints, you are creating a new value in memory, which exists as long as the method is executed. When the sum method is done, the sum int doesn't exist anymore. To retain its value, you need to return it from within the method, and assign it to a variable where you call the code.
Because Java is pass by value, but the value of reference types (including arrays) is a reference to the Object (in this case, a List). You might use a variadic function and (in Java 8+) an IntStream to implement it like
public static int sum(int... arr) {
return IntStream.of(arr).sum();
}
Then you can call sum with as many (or few) int arguments as you like.
Will print the returned value of array without defining as another
array as the was with the previous one ?
Whatever #yeedle mentioned above is correct, but one point to add as below:
ArrayList class (actual type of persons object) has overridden the toString() method such that it
could print the array details when you invoke
System.out.println(persons);.
You need to know that for your objects (created for your custom
classes like Product, Employee, etc..), you need to override
toString() method (inherited from java.lang.Object) to print the
values like how you wanted, otherwise simply using
System.out.println(object); will print the hashcode of the
object (like #HA5431 etc..).
You can look here and here
This method insert takes as input int[] array, int element, and int index, which inserts element into the index position of array. Since an array is not resizable, the method shifts every element over to the right of the array by one. The element at the end is removed from the array. The method returns void.
public class ShiftElements {
public static void insert(int[] array, int element, int index)
{
for (int i = array.length-1; i > index; i--)
{
array[i] = array[i-1];
}
array[index] = element;
}
}
To test if this method works, I changed the return type to int[] and wrote a main method to print array:
public class ShiftElements {
public static int[] insert(int[] array, int element, int index)
{
for (int i = array.length-1; i > index; i--)
{
array[i] = array[i-1];
}
return array;
}
public static void main(String[] args) {
System.out.print(insert(4,5,3));
}
}
I am having problems, getting this print statement to work. It's probably something simple, but I've been up for two days studying for finals so I'm pretty braindead.
I'm pretty sure I called the insert method just fine, but I think my issue is that I'm not properly inputting the type int[]. I'm not sure how I'm supposed to do this.
1) The first parameter of insert is an array of int, not an int. You must call :
insert(new int[]{4},5,3)
2) you can't print an array : so use :
println(Arrays.toString(insert(...)))
I guess what you are looking for is :
int[] i = new int[5];
System.out.print(java.util.Arrays.toString(insert(i,5,3)));
Apart from the use of java.util.Arrays.toString method Watch out the parameters that you are passing in insert method:
first parameter should be an array of int. But you are passing an int.
System.out.print(insert(4,5,3));
That statement does not pass a array of integers, you only passed and integer 4. You would need to pass, as your function is defined, int[], int, int.
System.out.print(insert(new int[4],5,3));
You made a call to insert(int,int,int) eventhough your signature for insert is insert(int[],int,int). For instance, calling insert with an array literal would be like so:
insert(new int[]{1,2,4,5}, 3, 2);
Additionally, System.arraycopy is a much faster and elegant way to copy arrays. You also seem to have forgotten to set the element at its index within your second example:
public static int[] insert(int[] array, int element, int index)
{
// Use arraycopy to shift all the elements by one, running over the last index
System.arraycopy(array, index, array, index+1, array.length-index-1);
// Set the appropriate index in the array to the specified value
array[index]=element;
return array;
}
If you then run the following, you will get your expected output:
int[] array = {1, 2, 4, 5};
insert(array,3,2); // array is now {1,2,3,4}
System.out.println(java.util.Arrays.toString(array));
If you are looking to print the array then the most laymen procedure is to return the particular array and loop throw it to print its element. eg:
public static void main(String[] args) {
int []solution= insert(new int[4],5,3);
for(int i=0;i<solution.length;i++)
{
System.out.println(solution[i]);
}
}
I'm doing a task for a course in Java programming and I'm not sure how the following thing is working? The method below takes the value from an array and a integer. The integer should be added to the array and then be used outside the method in other methods and so on, but how could this work when the method has no return for the new content of the array? There is a void in the method? Have I missed something? Preciate some help? Is there something about pointers?
public static void makeTransaction(int[] trans, int amount);
Arrays in Java are objects. If you modify the trans array inside the method, the changes will be reflected outside of it1. Eg:
public static void modify(int[] arr)
{
arr[0] = 10;
}
public static void main(...)
{
int x = {1, 2, 3};
System.out.println(x[0]); // prints 1
modify(x);
System.out.println(x[0]); // now it prints 10
}
Note that native arrays can't be dynamically resized in Java. You will have to use something like ArrayList if you need to do that. Alternatively you can change the return type to int[] and return a new array with the new element "appended" to the old array:
public static int[] makeTransaction(int[] trans, int amount)
{
int[] new_trans = Arrays.copyOf(trans, trans.length + 1);
new_trans[trans.length] = amount;
return new_trans;
}
1 It is also worth noting that as objects, array references are passed by value, so the following code has no effect whatsoever outside of the method:
public void no_change(int[] arr)
{
arr = new int[arr.length];
}
You can't add anything to an array. Java arrays have a fixed length. So indeed, what you want to do is impossible. You might make the method return an int[] array, but it would be a whole new array, containing all the elements of the initial one + the amount passed as argument.
If you want to add something to an array-like structure, use an ArrayList<Integer>.
Do you have to keep the method signature as is?
Also, can you be a bit more specific. When you say "the integer should be added to the array", are you referring to the amount argument? If so, then how is that amount added? Do we place it somewhere in the array or is it placed at the end, thus extending the array's length?
As far as pointers go, Java's pointers are implicit, so if you don't have a strong enough knowledge of the language, then it might not be so clear to you. Anyways, I believe that Java methods usually will pass objects by reference, and primitives by value. But, even that isn't entirely true. If you were to assign your object argument to new object, when the method terminates, the variable that you passed to the method is the same after the method executed as it was before. But, if you were to change the argument's member attributes, then when the method terminated those attributes values will be the same as they were inside of the method.
Anyways, back to your question, I believe that will work because an array is an object. So, if you were to do the following:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
}
// static int i;
/**
* #param args
*/
public static void main(String[] args)
{
int[] trans = {0,1,3};
makeTransaction(trans, 10);
for(int i = 0; i<trans.length; i++)
{
System.out.println(trans[i]);
}
}
The output of the array will be:
10
1
3
But, watch this. What if I decided to implement makeTransaction like so:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
trans = new int[3];
}
What do you think that the output will be? Will it be set to all zero's or will be the same as it was before? The answer is that the output will be the same as it was before. This ties in to what I was saying earlier.
I might've assigned that pointer to a new object in memory, but your copy of the pointer inside of the main method remains the same. It still points to the same place in memory as it did before. When the makeTransaction method terminates, the new int[3] object that I created inside of it is available for garbage collection. The original array remains intact. So, when people say that Java passes objects by reference, it's really more like passing objects' references by value.