Clean code - best way to compact code in Java - java

I have code that looks like this:
for(int i=0; i < a; i++){
List<Integer> list = elementA.get(i);
SomeClass rg = new SomeClass(list, a, methodA(i));
int result = rg.generate();
var+=methodA2(i, result);
}
for(int i=0; i < b; i++){
List<Integer> list = elementB.get(i);
SomeClass rg = new SomeClass(list, b, methodB(i));
int result = rg.generate();
var+=methodB2(i, result);
}
How can I avoid this code repetition? I can create function which does that, but what to do with this different methods?

With Java < 8 you can create an interface (note that there already is an IntFunction interface in Java 8):
interface IntFunction<A> { A apply (int i); }
m(elementA, a, new IntFunction<A> () { public A apply(int i) { methodA(i); } });
And your method would look like:
private void m(Collection<List<Integer>> element, int a, IntFunction<A> f) {
for(int i=0; i < a; i++){
List<Integer> list = element.get(i);
SomeClass rg = new SomeClass(list, a, f.apply(i));
int result = rg.generate();
}
}
(I have omitted the methodA2 for conciseness: you would need a second interface that has an apply(int, int))
That is quite verbose and the benefit is not obvious vs. repetition.
With Java 8 it becomes cleaner:
m(elementA, a, i -> methodA(i));
//or
m(elementA, a, this::methodA);

Define a method that receives your List<List<Integer>> as argument that returns the desired data.
Define an interface that will hold the generic methods like method, method2 (based from your code).
For example:
public long yourFooMethod(List<List<Integer>> listOfData, int n, SomeInterface foo) {
int i = 0;
long var = 0;
for(List<Integer> list : listOfData) {
SomeClass rg = new SomeClass(list, n, foo.method(i));
int result = rg.generate();
var += foo.method2(i, result);
}
return var;
}

Related

How to I call a method to create arrays from another class?

So I have this code in the main class
public class OneDArrays
{
public static int[] create (int size)
{
int[] a1 = new int[size];
for (int i = 0; i < size; i++)
{
a1[i] = i*2+1;
}
return a1;
}
public int sumSome (int[] b1, int howmany)
{
int sum = 0;
if (howmany <= b1.length)
{
for (int i = 0; i < howmany; i++)
{
sum = sum + b1[i];
}
}
else
{
sum = -1;
}
return sum;
}
public int[] grow (int[] c1, int extra)
{
int[] newArray = new int[c1.length+extra];
for (int i = 0; i < newArray.length; i++)
{
while (i <= c1.length)
{
newArray[i] = c1[i];
i++;
}
newArray[i] = 0;
}
return newArray;
}
public void print (int[] d1)
{
for (int i = 0; i < d1.length; i++)
{
System.out.println (d1[i] + ", ");
}
}
}
And then I have my tester class,
public class OneDArraysTester
{
public static void main (String[] args)
{
int[] test1;
test1.create (5);
}
}
How do retrieve the method from the first class? I get the error that "create" is an undeclared method. If the "create" method were a constructer, I know I could just type create test1 = new create (5) but I don't see a way to turn it in to a constructer, so what's the way of doing that but for a method?
You invoke a static method with the classname. Literally className.methodName. Like,
int[] test1 = OneDArrays.create(5);
You have made a class named OneDArrays so you can call it's methods by creating an instance or object of that class.
like this :
OneDArrays ObjectOfClass = new OneDArrays();
int test1[] = ObjectOfClass.create(5);
similarly you can also call other methods of that class by accessing methods of this newly created object ObjectOfClass.
like :
sumOfArray = ObjectOfClass.sumSome(test1,3);
int biggerTest1[] = ObjectOfClass.grow(test1,10);
If you want to make create method works as a constructor than you can but you cannot return value from a constructor so you cannot return your array from that constructor.
Since you have declared the create method as static, #ElliotFrisch is the best way. But, it is not always a good idea to make methods static. So another way to achieve what you want would be to make the create method non-static.
public int[] create (int size){/*Method Body*/};
And then create an object of the OneDArray class to access the method.
OneDArrays oneDArrays = new OneDArrays();
int[] test1 = oneDArrays.create(5);
or,
int[] test1 = new OneDArrays().create(5);

How to make java function take a list of objects of any class

I'm trying to write a Java function which takes a List of Lists holding objects of any class, and then calculates the size of the set consisting of all different combinations of inner list objects, where all objects come from different lists. The algorithm is simple:
int combos(List<List<Object>> inList) {
int res = 1;
for(List<Object> list : inList) {
res *= list.size();
}
return res;
}
But I'm getting this error when trying to run the function with a List<List<Integer>> object as input parameter:
List<List<Integer>> input = new ArrayList<List<Integer>>();
input.add(new ArrayList<Integer>());
input.get(0).add(1);
input.get(0).add(2);
combos(input);
The error:
The method combos(List<List<Object>>) in the type SpellChecker is not applicable for the arguments (List<List<Integer>>)
As far as I understand, Object is the parent class of Integer. So why doesn't this work? How can I make it work?
The relationship between Object and Integer does not apply to List<Object> and List<Integer>, see e.g. this related question for more details.
Use a type parameter:
<T> int combos(List<List<T>> inList) {
int res = 1;
for(List<T> list : inList) {
res *= list.size();
}
return res;
}
One solution is to use a type parameter in combos:
<T> int combos(List<List<T>> inList) {
int res = 1;
for(List<T> list : inList) {
res *= list.size();
}
return res;
}
This is closely related to this question about nested generics. The answer in that question provides some good info.
On top of the two good answers you already got here is another option.
public static void main(String[] args) {
List<List<Integer>> input = new ArrayList<>();
input.add(new ArrayList<>());
input.get(0).add(1);
input.get(0).add(2);
combos(input);
}
static int combos(List<? extends List<?>> inList) {
int res = 1;
for (List<?> list : inList) {
res *= list.size();
}
return res;
}
This also works, if you don't need to specialize the List Datatype as List<Integer>
List<List<Object>> input = new ArrayList<List<Object>>();
input.add( new ArrayList<Object>() );
input.get( 0 ).add( new Integer(1) );
input.get( 0 ).add( new Integer(2) );
combos( input );

How to pass array of structures to function in order to get results in JNA

I have the following function in C:
EXPORT int GetInfo(MyObject* &myObjects);
typedef struct MyObject
{
char info1[1025];
unsigned long sizeF;
char info2[20];
};
Then I invoke:
MyObject* list1;
int count = GetInfo(list1);
and iterate list1 in order to get information from each MyObject object (count -> number of elements in list1).
Now, I'm trying to make the counterpart in JNA. Thus, I have:
int GetInfo(PointerByReference myObjets);
public class MyObject extends Structure {
public static class ByReference extends MyObject implements Structure.ByReference {
}
public String info1;
public NativeLong sizeF;
public String info2;
public MyObject() {
}
public MyObject(Pointer pointer) {
super(pointer);
}
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"info1", "sizeF", "info2"});
}
}
Then:
PointerByReference ptrRef = new PointerByReference();
int count = myLib.GetInfo(ptrRef);
if (count > 0) {
Pointer pointer = ptrRef.getValue();
MyObject myObject = new MyObject(pointer);
MyObject[] myObjects = (MyObject[]) myObject.toArray(count);
}
Unfortunately, all fields in myObjects have default values (null/0).
I also tried:
int GetInfo(MyObject.ByReference myObjets);
MyObject.ByReference byRef = new PointerByReference();
int count = myLib.GetInfo(byRef);
if (count > 0) {
MyObject[] myObjects = (MyObject[]) byRef.toArray(count);
}
In this case, only the first field in first element of myObjects array was filled. The rest had default values.
What should I do in order to get an array of MyObjects with filled all fields.
Some time ago I found the solution. I don't know if it is wise, but it worked for me. So if someone will have a similar problem, then here you go:
In MyObject class I added 2 methods:
static MyObject[] fromArrayPointer(Pointer pointer, int numberResults) {
MyObject[] arr = new MyObject[numberResults];
int offset = 0;
for (int i = 0; i < numberResults; i++) {
arr[i] = fromPointer(pointer, offset);
offset += <size of structure>;
}
return arr;
}
static MyObject fromPointer(Pointer pointer, int offset) {
MyObject inst = new MyObject();
inst.info1= pointer.getString(offset);
offset += 1025;
inst.sizeF = pointer.getNativeLong(offset);
offset += 4; // long but 4 bytes because of machine
inst.info2 = pointer.getString(offset);
offset += 20;
return inst;
}
Honestly, you have to experiment with those numbers and size of structure. Remember about data aligment problem here.
Then, you have:
if (count > 0) {
MyObject[] myObjects = MyObject.fromArrayPointer(ptrRef.getValue(), count);
}

Java array object initialization

I just want ask, is it possible to initiliaze more objects with same constructor in one command?
Example of code:
Tile[] tiles = new Tile(5,5)[20];
Thanks for response.
Impossible as far as I know.
The code Tile[] tiles = new Tile[20]; just creates an array of references. To fill the array, you should create a Tile object and then assign the reference to one index of the array, such as:
tiles[0] = new Tile(5,5);
If all elements of the array pointing to the same object is OK, you can full fill the array simply use:
Tile tiles = new Tile[20];
Arrays.fill(tiles, new Tile(5,5));
No, you have to use a loop.
Tile[] tiles = new Tile[20];
for(int i = 0; i < tiles.length; i++) {
tiles[i] = new Tile(5, 5);
}
However, it is nice that in Java 8 we will be able to shorten this using the new Supplier class and a helper method.
static <E> E[] fill(E[] arr, Supplier<? extends E> supp) {
for(int i = 0; i < arr.length; i++) {
arr[i] = supp.get();
}
return arr;
}
We can then do the following:
Tile[] tiles = fill(new Tile[20], () -> new Tile(5, 5));
I think that's sort of nifty.
There's also a couple ways to do this without Java 8 by using reflection. Here's a way you can do it if the class has a copy constructor (a constructor that takes an object of its own class as an argument):
static <E> E[] duplicate(E[] arr, E element) {
#SuppressWarnings("unchecked")
Class<? extends E> cls = (Class<? extends E>)element.getClass();
try {
Constructor<? extends E> ctor = cls.getConstructor(cls);
for(int i = 0; i < arr.length; i++) {
arr[i] = ctor.newInstance(element);
}
} catch(Exception e) {
e.printStackTrace(System.err);
}
return arr;
}
So for example:
String[] arr = fill(new String[5], "Hello world!");
Reflection is a bit more unstable than the lambda, especially when dealing with subtypes and primitives. The lambda is great.
First, it is even not possible to initialize an object array with non-null value in one line (ok, except using {...} or filling them with same reference but I think it is not what you want)
You gotta create instance of array first, and fill individual element in the array:
e.g.
Foo[] myArray =new Foo[10];
for (int i = 0; i < myArray.length; ++i) {
myArray = new Foo();
}
If you are just looking for shorter code that you don't want to write the loop again and again, here is one option for you:
write a little util like this:
public class ArrayUtil {
public static T[] fillArray(T[] array, ArrayElementFactory elementFactory) {
for (int i = 0; i< array.length; ++i) {
array[i] = elementFactory.create(i);
}
return array;
}
}
public interface ArrayElementFactory<T> {
T create(int i);
}
The way to use is something like
Foo[] fooArray = fillArray(new Foo[10], new ArrayElementFactory<Foo>() {
Foo create(int i) { return new Foo(10,10); }};
If you are using Java8, I believe (haven't tried) you can use lambda expression which give you something like
Foo[] fooArray = fillArray(new Foo[10], i -> new Foo(10,10));

Performance static initialisation

which one is the best way to access static elements? Lets say that I have a class which will serve to share an static array of int.
option A
final class A {
static private int[] a;
static {
a = new int[1000];
for(int i = 0; i < a.length;i++) {
a[i] = i*50;
}
}
static int getA(int index) {
int tmp = a[index];
return tmp;
}
}
option B
final class B {
static private int[] b;
static int getB(int index) {
b = new int[1000];
for(int i = 0; i < b.length;i++) {
b[i] = i*50;
}
int tmp = b[index];
return tmp;
}
}
Access
public class Test {
public static void main(String[] args) {
int numA = A.getA(50);
System.out.println(numA);
int numB = B.getB(50);
System.out.println(numB);
}
}
Which one is the best in term of performance. Or is exactly the same thing;
thank in advance
The obvious difference between the A and B classes is that in the case of the latter, the int[] array would be initialized every time the getter is called. In the absence of further requirements, this seems unnecessary. So, I vote for using the A class implementation.
A is better than B. In B, each time the getB function is called, a new int[] is created, which will cost both time and memory space in heap. Also the for loop in getB may be executed multiple times.

Categories