Is there a more convenient way to initialize an array of objects than doing this?
SomeClass[] someArray = new SomeClass[100];
//...
for (int i = 0; i < someArray.length; i++) {
someArray[i] = new SomeClass();
}
// ...
Use Arrays.fill()
String[] stringArray = new String[100];
Arrays.fill(stringArray, "");
It's not any faster since it iterates over the array just like you did, but it is more convenient.
Arrays.fill() code
public static void fill(Object[] a, int fromIndex, int toIndex, Object val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i=fromIndex; i<toIndex; i++)
a[i] = val;
}
Because of the immutability of String in Java, your question is a bit strange. The primary thrust suggests you are looking for this:
String[] arr = new String[100];
Arrays.fill(arr, new String());//Array utility
However, this does not actually net you anything, because you will have to effectively create a new String object whenever you replace one of those array items with a different String. This means that the act of creating a new String() is redundant and therefore less efficient.
This begs the question: why are you doing this? Is it to ensure that there is a valid object being returned? Or that the object in the array is actually a String? If the latter, make use of generics:
List<String> arr = new ArrayList<String>();
This solves the same problem and nets you benefits of object-orientation. It is generally recommended you stay away from primitive arrays if you can: object-based arrays are far more usable, leading to cleaner code and often more efficient programs.
If you are using a mutable type, and the point of pre-filling is to ensure that an object exists when it's retrieved from the array, the best way to handle this is to actually use exceptions on the receiving end, for two reasons: the first being that you save memory by not allocating memory before you actually need it (and all the attendant savings that go along with that) and the second being that there is little stopping an array from having an element set to null, so you have to check anyway:
try {
SomeObject myObj = arr.get(idx);
myObj.doSomethingFun();//will fail if this is null!
} catch (NullPointerException e) {
//do something intelligent like return a fail case.
}
Note that while exceptions carry overhead if they catch an actual error, they have no overhead until that point. For this reason you don't want to use them for flow-of-control, but you do want to use them (more than you probably do) to catch edge cases that don't make sense.
This isn't quicker, but its less code:
String[] stringArray = new String[100];
Arrays.fill(stringArray, "");
So, you told you want to create array of distinct objects. Then there must be a default constructor or a factory that you pass in. I'll show code for first case - when you can call empty constructor with Class<...>.newInstance():
import java.lang.reflect.Array;
// ... in a class:
#SuppressWarnings("unchecked")
public static <T> T[] initializedArray(int size, Class<T> classHint) throws java.lang.Exception {
T[] result = (T[]) Array.newInstance(classHint, size);
for (int i = 0; i < size; ++i) {
result[i] = classHint.newInstance();
}
return result;
}
Example usage here: http://ideone.com/pbTFq9
you can declare like
String[] array;
...
array = new String[]{object1, object2};
Related
Here is my problem :
I want to create an array in a very clear and readable way, so that the reader can instantly know the elements of the array.
When the array is fixed, then it is easy and very clear :
String[] columns = new String[] { "unit", "file_row", "unit_row", "content" };
String[] types = new String[] { "INTEGER", "INTEGER", "INTEGER", "TEXT" };
But I also have variable arrays, depending on an argument :
// Is an argument of my method, containing the variable elements of the future array
String[] method_arg = new String[] {"key1", "key2"};
// The clear and readable way doesn't work anymore
String[] columns = new String[] { "unit", method_arg, "hash"};
String[] types = new String[] { "INTEGER", method_arg_types, "INTEGER"};
// And the ways that work are ... much less readable
String[] columns = new String[] {"unit"};
columns = Stream.concat(Arrays.stream(columns), Arrays.stream(method_arg)).toArray(String[]::new);
columns = Stream.concat(Arrays.stream(columns), Arrays.stream(new String[] {"hash"})).toArray(String[]::new);
// Awkward
String[] types = new String[method_arg.length + 2];
Arrays.fill(types, "TEXT");
types[0] = "INTEGER";
How do you make it so that the code stay clear and readable ?
The code is rather flexible, using lists should not be a problem, I'd prefer to avoid using non standard libraries though.
Also, I know a solution would be to create a method to create those arrays, like
join_arrays(new String[] {"unit"}, method_arg, new String[] {"hash"});
But if there are solutions making the code clear and avoiding the creation of a dedicated function, it would be better. If not I will fall back on this option.
Thank you, have a nice day !
I usually end up using a custom method for this sort of problem:
private <T> T[] makeArray(T... elements) {
return elements;
}
Your example would look like:
String[] columns = makeArray("unit", method_arg, "hash");
String[] types = makeArray("INTEGER", method_arg_types, "INTEGER");
I think you misinterpret the clarity and readability of code. First of all, you are completely RIGHT that clarity and readability of code are of the highest value. However, it doesn't mean that a reader should see immediately the outcome of the code - in your case the contents of the array. It means that the reader can clearly see first - WHAT the code does and second - HOW it does it. There are many ways to insure clarity.
Break your longer methods to shorter ones preferably 4 - 5 lines but at the most no longer than 10 - 15. Make sure that each method deals only with a single logically indivisible issue.
Make sure that method name is informative
The number of parameters is kept to a minimum (0 - 3)
The names and order of parameters are meaningful.
Return value matches the purpose of the method.
This, of course, is not a full list.
Java has an easier way for this, which is imho a little bit easier and is compiled away :-)
Example usage, similar to other suggestion:
private static void method(String method_arg, String method_arg_types) {
String[] columns = array("INTEGER", method_arg, "INTEGER");
String[] types = array("INTEGER", method_arg_types, "INTEGER");
}
The implementation is far easier, as a side effect of how var-args are implemented.
#SafeVarargs
public static <T> T[] array(T... values) {
return values;
}
Its also implemented in org.assertj.core.util, it should be part of the JDK imho :-)
There is a multidimensional String array being passed in as an Object.
I'm supposed to "unfold" it and process each of its primitive entries.
There's no way to know the dimensions other than by looking at the Object itself.
The difficulty i'm having is in casting. I can look up the array dimension by invoking its getClass().getName() and counting the [-s there.
But then how to cast it?
String[] sa = (String[]) arr;
is giving
Exception in thread "main" java.lang.ClassCastException: [[Ljava.lang.String; cannot be cast to [Ljava.lang.String;
Can this casting be done without any use of reflection?
Note - The array can be of any dimension - not just 1 or 2.
TIA.
If you want to work with an array which dimension is not known at the compile time, I would suggest you to recursively process all of its entries instead of trying to cast it.
You can use object.getClass().isArray() method to check if the current entry is an array and then iterate over it using Array.getLength(object) and Array.get(object, i):
public static void main(String[] args) {
Object array = new String[][] {new String[] {"a", "b"}, new String[] {"c", "d"}};
processArray(array, System.out::println);
}
public static void processArray(Object object, Consumer<Object> processor) {
if (object != null && object.getClass().isArray()) {
int length = Array.getLength(object);
for (int i = 0; i < length; i ++) {
Object arrayElement = Array.get(object, i);
processArray(arrayElement, processor);
}
} else {
processor.accept(object);
}
}
If the size of the array is not known statically (at compile time), then it's logically impossible to get the length relying solely on static means, i.e. without use of dynamic means.
Perhaps this question has the solution you need:
Getting the field "length" in a Java array using reflection
EDIT: This is NOT a duplicate of the above question. The original question concerns a list whose type is unknown at compile time. This question concerns an array like construct of a generic list.
For example the above solution of final E[] a = (E[]) Array.newInstance(c, s); won't work because I can not obtain List<MyClass>.class And also you can't cast from Object[] to List<MyClass>[]
What is the idiomatic way to deal with an array like construct of generic type? For example, I want an array of List<MyClass>. ArrayList<List<MyClass>> myClassArray won't work directly because I need to be able to do things like myClassArray.set(5, myClassObj) even when the myClassArray.size() is 0. Initialize it with
for(int i = 0; i < mySize; i ++){
myClassArray.add(null)
}
works but it's ugly.
List<MyClass> myClassArray[] won't work either because you can't create a generic array. So what is the most idiomatic way to achieve my goal? The size of array won't change once created.
Create your own class to simulate an array.
class Array<T> {
final Object[] data;
public Array(int size) {
data = new Object[size];
}
public void set(int index, T datum) {
data[index] = datum;
}
#SuppressWarnings("unchecked")
public T get(int index) {
return (T) data[index];
}
}
Since you control the access to the underlying array, you know that the elements in there will all be of type T.
The usual way is
List<MyClass>[] myClassArray = new List[size];
The reason why the type of array of parameterized types is "unsafe" is very obscure (because arrays are supposed to check at runtime when you put something into it that it's an instance of the component type, but it's not possible to actually check the parameter for a parameterized type) and not relevant for your purposes.
I have the next scenario:
I define an int[][] variable in my main class. int[][] matrix1 = new int[10][10] and i give it some values. I then call a method and i send this variable as a parameter to that method. Being an object it sends is by reference not by value, so inside the method, because i have to change the values contained by matrix1 but not affect the object after it returns from the method, i make a clone of it like so:
private void myMethod( int[][] matrix1 )
{
int[][] matrix1Clone = matrix1.clone();
//And next i do some changes to matrix1Clone
......
}
But the problem is that the changes i do to matrix1Clone also happen in matrix1. So it hasn't really created a clone of matrix1 object, but both variables point to the same object.
Why is this? I can't seem to figure it out. Why doesn't clone method work?
If you need more info, please ask. But i'm afraid this is about it, can't really give you more, but maybe i could try.
I might be missing something, but i can't figure out what...
Thanks.
EDIT
Sorry, made a typo. It's late hre and i'm tired. I'm using clone method indeed, that's why i'm confused as it's not working :(.
Try clone it using clone() http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#clone%28%29
private void myMethod( int[][] matrix1 )
{
int[][] matrix1Clone = matrix1.clone();
}
or, copy all of the values using a loop
EDIT: Api for clone() says it should return a copy of the object, but behavior might be different depending on which object's beeing cloned. Try iterating over the array as an alternative. Since it's a 2d array, you need a nested loop:
for(int i=0; i<old.length; i++)
for(int j=0; j<old[i].length; j++)
old[i][j]=copy[i][j];
where old is the "original array" and copy is the copy
You are giving matrix1Clone same reference as matrix1. If you change matrix1Clone then matrix1 changes too.
You can copy your array with iterating over the source array:
public static int[][] clone2DArray(int[][] array) {
int rows = array.length;
//clone the 'shallow' structure of array
int[][] newArray = array.clone();
//clone the 'deep' structure of array
for(int row = 0; row < rows; row++){
newArray[row] = array[row].clone();
}
return newArray;
}
Actually, arrays have no values but pointers towards object or primitive datatypes. If you want a detailed answer, you should read my commentary here: Java is NEVER pass-by-reference, right?...right? or here: In Java, what is a shallow copy?
So, as arrays are pointers, what happens if you clone a pointer with pointers in it? At first, the pointers are copied for real, but these pointers only point toward other object which aren't cloned. So if you want to clone, I suggest not using arrays but "harder" data structures: classes. Another possibility would to never store an array within an array...like I use arrays only for containers!
But I can't give you details about Java multidimensional generics, as I never deal with them, not only because of their possible inconsistency because they are arrays (they're violating some OO principles anyway and make code looking ugly).
EDIT
I was running a few tests how the clone method works for arrays inside a class, what the problem is and which workarounds we have.
First the test data structure:
public class Foobar implements Cloneable {
String[] array;
public Foobar() {
this.array = new String[10];
}
public String getValue(){
return array[0];
}
public String[] getArray(){
return array;
}
public void setArray(String[] array){
this.array = array;
}
#Override
public Object clone(){
try{
Foobar foobar = (Foobar) super.clone();
foobar.setArray(array);
return foobar;
}
catch(Exception e){
return null;
}
}
}
Now the controller:
String[] array = new String[10];
array[0] = "111";
Foobar foo1 = new Foobar();
foo1.setArray(array);
Foobar foo2 = foo1; //Alternation: Foobar foo2 = (Foobar) foo1.clone();
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
array[0] = "999";
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
The test results will always look like that - no matter if I use = or clone():
Instance: [Ljava.lang.String;#42e816 with value: 111
Instance: [Ljava.lang.String;#42e816 with value: 111
Instance: [Ljava.lang.String;#42e816 with value: 999
Instance: [Ljava.lang.String;#42e816 with value: 999
This is not good!!
So what is the workaround? I suggest doing this in every data structure class:
public class Foobar implements Serializable {
//any class variables...it doesn't matter which!
public Foobar() {
//do initialisation here...it doesn't matter what you do!
}
public Foobar copy(){
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Foobar foobar = (Foobar) ois.readObject();
return foobar;
}
catch(Exception e){
return null;
}
}
}
So you will get a full copy by implementing just one line of code:
Foobar foo2 = foo1.copy(); //nice and easy!!
The advantage of this solution: It's usually enough to implement the interface Serializable to make a class "copyable". And if not, you can solve any issues by reading what is written in the Serializable Javadoc!
Even more: It doesn't matter what kind of objects are in the class you want to make "copyable", so you don't need to spend any more time on this issue. After all, above code is the simpliest and fastest solution deeply embedded in Java ever since and uses only RAM! (thanks to ByteArrayOutputStream)
Enjoy!
UPDATE: Note that you only need to use an object's copy if you want a temporary stack or if you are dealing with threads (in general: if you need to have objects fully independent from each other). Otherwise you shouldn't make any copy at all! Also if you write some data into a file or a socket, you don't need a copy. Even more I suggest to implement the copy method only when it's really used: for data structures (model). So be careful by using this mighty method (otherwise it could slow down your app, or even fill up the Java VM storage if you make millions of copies with no reason, this would cause a stackoverflow indeed :o).
EDIT
I was working a bit more on the this issue. Because I suddenly found out, that there is a public clone() method of "primitive" arrays that aren't in the Java API !! (a "easter egg" from SUN for arrays like String[] or int[] ;-)
And as I use real arrays as the basic data structure of Foobar (not ArrayLists!), I can change the clone method (of above class) like this:
#Override
public Object clone(){
try{
Foobar foobar = (Foobar) super.clone();
String[] arrayClone = array.clone(); //who thought that this is possible?!
foobar.setArray(arrayClone);
return foobar;
}
catch(Exception e){
return null;
}
}
And now we get this result right out of the box:
Instance: [Ljava.lang.String;#42e816 with value: 111
Instance: [Ljava.lang.String;#9304b1 with value: 111
Instance: [Ljava.lang.String;#42e816 with value: 999
Instance: [Ljava.lang.String;#9304b1 with value: 111
Problem solved with "double-nested" objects!!! As you can see, the clones have different objects independently from the original...therefore foo1.equals(foo2)) will be false!
Solution: In the clone method of a class, you need to clone all its class variables, too! (But if some class variables are ArrayLists or more-dimensional arrays, even this solution won't work!)
Finally, what is the real issue? The class ArrayList doesn't clone it's arrays, it only calls the method copyOf in the class Array, which is harmful. So never use the clone method of the class ArrayList, and never inherit any class from ArrayList because its clone method won't work! (It works only if the class ArrayList only contains primitives and no objects...otherwise just use the easy ByteArray solution above!).
Note that with more-dimension arrays like Object[][] you always need to implement the ByteArray solution above, they can't be cloned! And if your array is huge, it may take a while and need some RAM, too.
Now you are a cloning expert! :-D
With a third party API I observed the following.
Instead of using,
public static string getString(){
return "Hello World";
}
it uses something like
public static void getString(String output){
}
and I am getting the "output" string assigned.
I am curious about the reason of implementing such functionality. What are the advantages of using such output parameters?
Something isn't right in your example.
class Foo {
public static void main(String[] args) {
String x = "foo";
getString(x);
System.out.println(x);
}
public static void getString(String output){
output = "Hello World"
}
}
In the above program, the string "foo" will be output, not "Hello World".
Some types are mutable, in which case you can modify an object passed into a function. For immutable types (such as String), you would have to build some sort of wrapper class that you can pass around instead:
class Holder<T> {
public Holder(T value) {
this.value = value;
}
public T value;
}
Then you can instead pass around the holder:
public static void main(String[] args) {
String x = "foo";
Holder<String> h = new Holder(x);
getString(h);
System.out.println(h.value);
}
public static void getString(Holder<String> output){
output.value = "Hello World"
}
That example is wrong, Java does not have output parameters.
One thing you could do to emulate this behaviour is:
public void doSomething(String[] output) {
output[0] = "Hello World!";
}
But IMHO this sucks on multiple levels. :)
If you want a method to return something, make it return it. If you need to return multiple objects, create a container class to put these objects into and return that.
I disagree with Jasper: "In my opinion, this is a really ugly and bad way to return more than one result".
In .NET there is a interesting construct that utilize the output parameters:
bool IDictionary.TryGet(key, out value);
I find it very usefull and elegant. And it is the most convenient way to aks if an item is in collection and return it at the same time. With it you may write:
object obj;
if (myList.TryGet(theKey, out obj))
{
... work with the obj;
}
I constantly scold my developers if I see old-style code like:
if (myList.Contains(theKey))
{
obj = myList.Get(theKey);
}
You see, it cuts the performance in half. In Java there is no way to differentiate null value of an existing item from non-existance of an item in a Map in one call. Sometimes this is necessary.
This functionality has one big disadvantage - it doesn't work. Function parameters are local to function and assigning to them doesn't have any impact outside the function.
On the other hand
void getString(StringBuilder builder) {
builder.delete(0, builder.length());
builder.append("hello world");
}
will work, but I see no advantages of doing this (except when you need to return more than one value).
Sometimes this mechanism can avoid creation of a new object.
Example:
If an appropriate object exists anyhow, it is faster to pass it to the method and get some field changed.
This is more efficient than creating a new object inside the called method, and returning and assigning its reference (producing garbage that needs to be collected sometime).
String are immutable, you cannot use Java's pseudo output parameters with immutable objects.
Also, the scope of output is limited to the getString method. If you change the output variable, the caller won't see a thing.
What you can do, however, is change the state of the parameter. Consider the following example:
void handle(Request r) {
doStuff(r.getContent());
r.changeState("foobar");
r.setHandled();
}
If you have a manager calling multiple handles with a single Request, you can change the state of the Request to allow further processing (by other handlers) on a modified content. The manager could also decide to stop processing.
Advantages:
You don't need to return a special object containing the new content and whether the processing should stop. That object would only be used once and creating the object waste memory and processing power.
You don't have to create another Request object and let the garbage collector get rid of the now obsolete old reference.
In some cases, you can't create a new object. For example, because that object was created using a factory, and you don't have access to it, or because the object had listeners and you don't know how to tell the objects that were listening to the old Request that they should instead listen to the new Request.
Actually, it is impossible to have out parameters in java but you can make a work around making the method take on a de-reference for the immutable String and primitives by either writing a generic class where the immutable is the generic with the value and setter and getter or by using an array where element 0 (1 in length) is the value provided it is instantiate first because there are situations where you need to return more than one value where having to write a class just to return them where the class is only used there is just a waste of text and not really re-usable.
Now being a C/C++ and also .Net (mono or MS), it urges me that java does not support at least a de-reference for primitives; so, I resort to the array instead.
Here is an example. Let's say you need to create a function (method) to check whether the index is valid in the array but you also want to return the remainding length after the index is validated. Let's call it in c as 'bool validate_index(int index, int arr_len, int&rem)'. A way to do this in java would be 'Boolean validate_index(int index, int arr_len, int[] rem1)'. rem1 just means the array hold 1 element.
public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
if (index < 0 || arr_len <= 0) return false;
Boolean retVal = (index >= 0 && index < arr_len);
if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));
return retVal;
}
Now if we use this we can get both the Boolean return and the remainder.
public static void main(String[] args)
{
int[] ints = int[]{1, 2, 3, 4, 5, 6};
int[] aRem = int[]{-1};
//because we can only scapegoat the de-ref we need to instantiate it first.
Boolean result = validate_index(3, ints.length, aRem);
System.out.println("Validation = " + result.toString());
System.out.println("Remainding elements equals " + aRem[0].toString());
}
puts: Validation = True
puts: Remainding elements equals 2
Array elements always either point to the object on the stack or the address of the object on the heap. So using it as a de-references is absolutely possible even for arrays by making it a double array instantiating it as myArrayPointer = new Class[1][] then passing it in because sometimes you don't know what the length of the array will until the call going through an algorithm like 'Boolean tryToGetArray(SomeObject o, T[][] ppArray)' which would be the same as in c/c++ as 'template bool tryToGetArray (SomeObject* p, T** ppArray)' or C# 'bool tryToGetArray(SomeObject o, ref T[] array)'.
It works and it works well as long as the [][] or [] is instantiate in memory first with at least one element.
in my opinion, this is useful when you have more than one result in a function.