Java function for int[], float[] or double[] array - java

I want to write a Java function that will get as input either int[], float[] or double[]. The algorithm is exactly the same (some kind of a scalar product). How can I write a single function that will be able to handle all types of numeric arrays?

There is no easy way to handle this in Java. You can:
Use Wrapper types (Integer[], Float[], Double[]) and have a function taking Number[] as an argument. Works since arrays are covariant in Java:
public static void main(String[] args) {
f(new Integer[]{1,2,3});
f(new Float[]{1,2,3});
f(new Double[]{1,2,3});
}
private static void f(Number[] numbers) {
f[0].doubleValue();
}
Note that this approach increases memory consumption significantly.
Convert int[] and float[] arrays to double[] and work with doubles all along. Preferably create overloaded versions of your method where the ones taking int[] and float[] are only doing the conversion and delegate to actual double[] implementation.
I believe Scala can handle this seamlessly as Java primitive types are semantically objects in Scala.

You cannot code this in Java without either:
coding each case separately or,
using reflection for all operations on the array ... which is likely to be messy, fragile and an order of magnitude slower than an optimal solution.
The only common supertype of int[] float[] and double[] is Object, so there is no possibility of a solution using polymorphism over those types. Likewise, generics require that the type parameter is a reference type, and int, float and double are not reference types.
You either need to accept that you will have duplicate code, or change the representation type for the arrays; e.g. use Integer[] / Float[] / Double[] or Number[].

You can write one method to do them all, however, it won't be anywhere near as readable of efficient. You have to make a choice between what is a generic or an efficient solution.
public static void main(String... args) throws IOException {
int[] nums = new int[10*1000 * 1000];
{
long start = System.nanoTime();
product2(nums);
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to take the product of %,d ints using an int[].%n", time / 1e9, nums.length);
}
{
long start = System.nanoTime();
product(nums);
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to take the product of %,d ints using reflections.%n", time / 1e9, nums.length);
}
}
public static double product(Object array) {
double product = 1;
for (int i = 0, n = Array.getLength(array); i < n; i++)
product *= ((Number) Array.get(array, i)).doubleValue();
return product;
}
public static double product2(int... nums) {
double product = 1;
for (int i = 0, n = nums.length; i < n; i++)
product *= nums[i];
return product;
}
prints
Took 0.016 seconds to take the product of 10,000,000 ints using an int[].
Took 0.849 seconds to take the product of 10,000,000 ints using reflections.
If you are only working on relatively small arrays, the generic but less efficient solution may be fast enough.

Use java.lang.Number type or Object parameter type.
For more info read Bounded Type Parameters

I see two options:
1) You can create a new class which allows int[], float[], double[] in the contructor and saves them.
2) You allow Object[] and check for int / float / double. (You have to convert them first)

class ArrayMath {
private ArrayMath() {
}
public static <T extends Number> double ScalarProduct(T[] a, T[] b){
double sum = 0;
for(int i=0;i<a.length;++i){
sum += a[i].doubleValue()*b[i].doubleValue();
}
return sum;
}
}
class Sample {
public static void main(String arg[]){
Integer[] v1 = { 1, -10, 3, 9, 7, 99, -25 };
Integer[] v2 = { 1, -10, 3, 9, 7, 99, -25 };
double p_int = ArrayMath.ScalarProduct(v1, v2);
Double[] v1_d = { 1.1, -10.5, 3.7, 9.98, 7.4, 9.9, -2.5 };
Double[] v2_d = { 1.1, -10.5, 3.7, 9.98, 7.4, 9.9, -2.5 };
Double p_double = ArrayMath.ScalarProduct(v1_d, v2_d);
System.out.println("p_int:" + p_int);
System.out.println("p_double:" + p_double);
}
}

Hope this will help you.. I have tested this code and it does what you have asked for, how to implement this logic is upto you !
public class MultiDataType {
public static void main(String[] args) {
int[] i = new int[2];
float[] f = new float[2];
double[] d = new double[2];
String str = new String();
handlingFunction(i);
handlingFunction(f);
handlingFunction(d);
handlingFunction(str);
}
public static void handlingFunction(Object o) {
String classType = null;
if (o.getClass().getCanonicalName().equals("int[]")) {
classType = "int[]";// Your handling code goes here
} else if (o.getClass().getCanonicalName().equals("float[]")) {
classType = "float[]";// Your handling code goes here
} else if (o.getClass().getCanonicalName().equals("double[]")) {
classType = "double[]";// Your handling code goes here
}else classType = o.getClass().getCanonicalName();
System.out.println("Object belongs to " + classType);
}
}
OUTPUT
Object belongs to int[]
Object belongs to float[]
Object belongs to double[]
Object belongs to java.lang.String

Related

How to take average of Double[] in java

I have a map like following
Map<String, Double[]> userVecs;
userVecs.put("foo", [1.1, 2.2, 3.3]);
userVecs.put("bar", [0, 4, 2]);
I want an average vec which in this case is:
[1.1+0, 2.2+4, 3.3+2] / 2;
= [0.55, 3.1, 2.65]
I have an ugly two loop approach. I was wondering if there is a better way to do this.
Here is one way. It presumes the arrays are all the same length.
declare a sum array of the proper length.
iterate over the map values and add them via Arrays.setAll()
then find the average using userVecs.size() and Arrays.setAll()
Map<String, double[]> userVecs = new HashMap<>();;
userVecs.put("foo", new double[]{1.1, 2.2, 3.3});
userVecs.put("bar", new double[]{0, 4, 2});
double[] sums = new double[userVecs.get("foo").length];
for (double[] dar : userVecs.values()) {
Arrays.setAll(sums, i->sums[i]+dar[i]);
}
Arrays.setAll(sums, i->sums[i]/userVecs.size());
System.out.println(Arrays.toString(sums));
prints
[0.55, 3.1, 2.65]
The Arrays class has many useful features you may want to get familiar with.
Unless you want to use an external Math library, you're gonna wanna just write the extra function.
public static void main(String[] args) {
double[] arr1 = { 1.0, 2.0, 3.0 };
double[] arr2 = { 1.0, 1.0, 1.0 };
double[] avg = elementWiseAvg(arr1, arr2);
}
public static double[] elementWiseAvg(double[] arr1, double[] arr2) {
if (arr1.length != arr2.length) {
throw new IllegalArgumentException("Arrays must be the same length.");
}
double[] ret = new double[arr1.length];
for (int i = 0; i < arr1.length; ++i) {
ret[i] = (arr1[i] + arr2[i]) / 2;
}
return ret;
}
You have a two-loop approach, but that's not necessarily ugly. What you are effectively doing is summing two matrices of a single dimension. Like was pointed out in another answer unless you want to import a math library, you're going to have to roll your own.
If you would like to explore an external library, look to jblas, it's a linear algebra library for Java. Here's an example of summing and averaging those two vectors using jblas.
DoubleMatrix matrix1 = new DoubleMatrix(3, 1, 1.1, 2.2, 3.3);
DoubleMatrix matrix2 = new DoubleMatrix(3, 1, 0, 4, 2);
DoubleMatrix sum = matrix1.addColumnVector(matrix2).div(2);
log.info(sum);
The output is [0.550000; 3.100000; 2.650000]
Here is a solution with Java 8 Streams.
The approach is to create a stream over the values of the given map, i.e. a stream of arrays Double[]. Then inside a collector, created using Collector.of() sum up array values for every index and as a final step divide each the value at each index by the map size.
In order to preserve arrays in the source map intact, we need to find out the length of these array and collect the data into a newly created array.
public static Double[] getAverage(Map<String, Double[]> userVecs) {
if (userVecs.isEmpty()) {
return new Double[0]; // throw an exception depending on your needs
}
int size = userVecs.values().iterator().next().length; // the map is proved to be non-empty, we can safely access one of its elements to find out the size of the resulting array
return userVecs.values().stream()
.collect(Collector.of(
() -> Stream.generate(() -> 0d).limit(size).toArray(Double[]::new), // mutable container
(Double[] res, Double[] next) -> mergeArrays(res, next), // accumulator - populating the container
(left, right) -> mergeArrays(left, right), // combiner - merging containers while executing in parallel
res -> toAverage(res, userVecs.size()) // finisher - transforming the container into a final result
));
}
public static Double[] mergeArrays(Double[] res, Double[] next) {
for (int i = 0; i < res.length; i++) res[i] += next[i];
return res;
}
public static Double[] toAverage(Double[] res, int mapSize) {
for (int i = 0; i < res.length; i++) res[i] /= mapSize;
return res;
}
main()
public static void main(String[] args) {
Map<String, Double[]> userVecs = new HashMap<>();
userVecs.put("foo", new Double[]{1.1, 2.2, 3.3});
userVecs.put("bar", new Double[]{0d, 4d, 2d});
System.out.println(Arrays.toString(getAverage(userVecs)));
}
Output:
[0.55, 3.1, 2.65]

Java, Creating an object vector that should have n zeros in it's array after compilation

This is kind of hard but I will try to make my question as clear as possible.
So I'm working on a project that deals with operations on vectors. I have different classes for different dimensions: Vector3D, Vector5D and VectorND. So I have interface and abstract class that describe methods like Sum, Subtraction etc. And for result of operation I create a new object Vector where I put coordinates after sum/subtraction etc. So here is the part of code as an example:
interface sample
{
Vector Sum(Vector vec);
Vector Subtraction(Vector vec);
int Product(Vector vec);
boolean Compare(Vector vec);
String ToString();
}
abstract class Vector implements sample
{
int[] coordinates;
public Vector (int[] coordinates)
{
this.coordinates=coordinates;
}
protected abstract Vector resVec();
public Vector Sum(Vector vec)
{
Vector result = resVec();
if (this.coordinates.length == vec.coordinates.length)
{
for (int i = 0; i< vec.coordinates.length; i++)
{
result.coordinates[i] = this.coordinates[i] + vec.coordinates[i];
}
}
else
{
throw new ArithmeticException("Can't sum vectors of different length");
}
return result;
Here is have protected abstart Vector resVec(); - method that creates new vector with length that depends on dimension of vectors that we operate with.
Example of realization for Vector3D:
class Vector3D extends Vector
{
public Vector3D(int n1,int n2,int n3)
{
super(new int[]{n1,n2,n3});
}
public Vector3D resVec()
{
Vector3D resVec = new Vector3D(0,0,0);
return resVec;
}
So here I create a new vector with length 3 and fill it with zeros. I need to create same vector for VectorND. Like this:
class VectorND extends Vector
{
public VectorND(int...n)
{
super(n);
}
public VectorND resVec()
{
VectorND resVec = new VectorND();
return resVec;
}
Any ideas how I can pass not declared number of zeros? Or maybe any idea of different implementation? Thanks!
Within the resVec() method, you can populate an array of 0s and then pass it to your Vector super constructor. Since your super constructor takes an array of ints, you could do something like this:
public VectorND resVec(int n)
{
int[] coordinates = new int[n];
Arrays.fill(coordinates, 0);
VectorND resVec = new VectorND(coordinates);
return resVec;
}
Foremost you could make use of generics since you would get problems as soon you need float or double for a vector type.
public interface Vector<T extends Number>{
T getX();
void setX(T x);
// [...]
T length();
T lengthSquared();
// [...]
To your problem, it can be solved by adding a helper variable which contains the dimension amount and than process the math operations as algorthm / loop. This way the amount of dimension don't matter anymore and you also avoid issues like divide by zero.
this is a excample for a matrix .. but the aproche is the same:
public final void multiply(float factor) {
// in your case it would be getDimension() or something
for(int i = 0; i < getRows()*getColumns();++i){
m[i]*=factor;
}
}
Oh and I know this advice is hard for java developer but don't over engineer it otherwise you will waste preformence.
The values of arrays are automatically defaulted.
int[] ints = new int[4]; // Filled with 0
double[] doubles = new double[5]; // Filled with 0.0
boolean[] booleans = new boolean[6]; // Filled with false
String[] strings = new String[7]; // Filled with null
I am not entirely sure about your classes, but for a multi-dimensional matrix-like class one only needs one version. The values can be stored in a linearized array by using a calculated index.
public class DoubleMatrix {
final int[] sizes;
final double[] values;
public DoubleMatrix(int... sizes) {
this.sizes = Arrays.copyOf(sizes, sizes.length); // Or sizes.clone()
int valueCount = 1;
for (int size : this.sizes) {
assert size > 0 : "Every given size must be at least 1.";
valueCount *= size;
}
values = new int[valueCount];
}
public int dimesion() {
return sizes.length;
}
public double get(int... is) {
int i = index(is);
return values[i];
}
// new DoubleMatrix(2, 3, 4).set(3.14259, 0, 1, 2); // 24 values in 3D
public void set(double x, int... is) {
int i = index(is);
values[i] = x;
}
The setter is a bit unconventional placing the value first because of the var-args is.
The linearisation from several indices to an index into the values array:
private int index(int... is) {
assert is.length == sizes.length: "Wrong number of indices.";
int singleI = 0;
for (int dim = 0; dim < sizes.length) {
if (0 > is[dim] || is[dim] >= sizes[dim]) {
throw new IndexOutOfBoundsException();
}
if (dim > 0) {
singleI *= sizes[i - 1];
}
singleI += is[i];
}
}
(I am not sure the index calculation is correct.)
Instead of asserts throwing runtime exceptions (IllegalArgumentException) would be better.
Of course if get and set were protected you could make a child class without var-args, and have a public get(int i, int j) for a DoubleMatrix2D.

In convertible cast, casting from T to double

I want to create generic method for getting maximal value from the array. However I got stuck at the problem of conversion between T to type Math.max method uses.
here is my code:
First I cannot initialize the maxValue like:
T maxVaue = 0;
secondly I cannot use data[i] in Math.max, in both cases I got error of In convertible cast.
class Matrix<T>{
public T getMaxValue(T[] data){
T maxValue;
for (int i=0; i<data.length; i++){
maxValue = Math.max(data[i], maxValue);
}
return maxValue;
}
}
Math.max takes only int, float, double and long. So you can not use it with T.
What you can do is write your own max() method using T. For example, your method could take a Comparator object in param. Or your T objects can implement the Comparable interface.
Have a look at this post : How to implement a generic `max(Comparable a, Comparable b)` function in Java?
You cannot do that as you are doing it because a T can be anything. You could e.g. limit T to a Number but then you'd have to choose an intermediate primitive type and you will still run into issues returning the value.
However, you could just limit T to Comparable and use that instead, e.g.:
class Matrix<T extends Comparable<T>>{
public T getMaxValue(T[] data){
T maxValue = null;
for (int i=0; i<data.length; i++){
if (maxValue == null || data[i].compareTo(maxValue) > 0)
maxValue = data[i];
}
return maxValue;
}
}
All of Java's primitive wrapper types implement Comparable, as well as many other types:
byte by = new Matrix<Byte>().getMaxValue(new Byte[]{1, 2, 3});
char ch = new Matrix<Character>().getMaxValue(new Character[]{'a', 'b', 'c'});
int in = new Matrix<Integer>().getMaxValue(new Integer[]{1, 2, 3});
short sh = new Matrix<Short>().getMaxValue(new Short[]{1, 2, 3});
long lo = new Matrix<Long>().getMaxValue(new Long[]{1L, 2L, 3L});
float fl = new Matrix<Float>().getMaxValue(new Float[]{0.1f, 0.2f, 0.3f});
double db = new Matrix<Double>().getMaxValue(new Double[]{0.1, 0.2, 0.3});
boolean bo = new Matrix<Boolean>().getMaxValue(new Boolean[]{false, true});
String st = new Matrix<String>().getMaxValue(new String[]{"turtles", "are", "weird"});
BigInteger bi = new Matrix<BigInteger>().getMaxValue(new BigInteger[]{...});
T can hold only classes like Double, Integer, not primitive types like double, int. Maybe just use built-in Collections.max(Collection<T extends Comparable<T>>) and array of Doubles instead of doubles like in this code example
class Matrix<T extends Comparable<T>> {
public T getMaxValue(T[] data) {
return Collections.max(Arrays.asList(data));
}
public static void main(String[] args) throws IOException {
Matrix<Double> m = new Matrix<>();
System.out.println(m.getMaxValue(new Double[] { 1., 42., 3., 4., 5. }));
}
}

Java Arrays.binarySearch with compareTo

I need to use Arrays.binarySearch on an array of custom objects. Here is the object:
class Range implements Comparable<Range>{
public int bottom;
public int top;
public Range(int botIn, int topIn) {
this.bottom = botIn;
this.top = topIn;
}
#Override
public int compareTo(Range compareRange) {
int compareQuantity = ((Range) compareRange).bottom;
return this.bottom - compareQuantity;
}}
In my main I first call Arrays.sort(lowerBounds); where lowerBounds is an array of Range elements. This works just fine and sorts them using the compareTo I wrote. Then I call Arrays.binarySearch(lowerBounds, 0) but I get "Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to compareToTest.Range".
What am I doing wrong? Thank you.
Edit: here is main:
public static void main(String[] args)
{
int[] A = {1, 5, 2, 1, 4, 0};
// write your code in Java SE 6
Range[] lowerBounds = new Range[A.length];
for(int i=0; i< A.length; i++)
{
lowerBounds[i] = new Range(i-A[i], i+A[i]);
}
Arrays.sort(lowerBounds);
for(int i=0; i< A.length; i++)
{
System.out.println(lowerBounds[i].bottom);
}
System.out.println(Arrays.binarySearch(lowerBounds, 0));
}
Arrays.binarySearch accepts two parameters - an array to search in, and the object you're looking for. You have supplied an array of Range object and an int (which is autoboxed to an Integer). Naturally, you can't search for an Integer in an array of Ranges.
Instead, you should create the Range object you're looking for. E.g.:
Range r = new Range (0, 0);
Arrays.binarySearch (lowerBounds, r);
Arrays.binarySearch(lowerBounds, 0) is wrong because you are comparing Range Objects.SO you need to pass a Range Object instead of an Integer Object which results in java.lang.ClassCastException: java.lang.Integer cannot be cast to compareToTest.Range"
You need to create a RangeObject and pass it in binarySearch method
Range r = new Range(0,<any integer>)
Arrays.binarySearch (lowerBounds, r);

Is there possibility of sum of ArrayList without looping

Is there possibility of sum of ArrayList without looping?
PHP provides sum(array) which will give the sum of array.
The PHP code is like
$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";
I wanted to do the same in Java:
List tt = new ArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
Once java-8 is out (March 2014) you'll be able to use streams:
If you have a List<Integer>
int sum = list.stream().mapToInt(Integer::intValue).sum();
If it's an int[]
int sum = IntStream.of(a).sum();
Then write it yourself:
public int sum(List<Integer> list) {
int sum = 0;
for (int i : list)
sum = sum + i;
return sum;
}
The only alternative to using a loop is to use recursion.
You can define a method like
public static int sum(List<Integer> ints) {
return ints.isEmpty() ? 0 : ints.get(0) + ints.subList(1, ints.length());
}
This is very inefficient compared to using a plain loop and can blow up if you have many elements in the list.
An alternative which avoid a stack overflow is to use.
public static int sum(List<Integer> ints) {
int len = ints.size();
if (len == 0) return 0;
if (len == 1) return ints.get(0);
return sum(ints.subList(0, len/2)) + sum(ints.subList(len/2, len));
}
This is just as inefficient, but will avoid a stack overflow.
The shortest way to write the same thing is
int sum = 0, a[] = {2, 4, 6, 8};
for(int i: a) {
sum += i;
}
System.out.println("sum(a) = " + sum);
prints
sum(a) = 20
Write a util function like
public class ListUtil{
public static int sum(List<Integer> list){
if(list==null || list.size()<1)
return 0;
int sum = 0;
for(Integer i: list)
sum = sum+i;
return sum;
}
}
Then use like
int sum = ListUtil.sum(yourArrayList)
for me the clearest way is this:
doubleList.stream().reduce((a,b)->a+b).get();
or
doubleList.parallelStream().reduce((a,b)->a+b).get();
It also use internal loops, but it is not possible without loops.
You can use apache commons-collections API.
class AggregateClosure implements org.apache.commons.collections.Closure {
int total = 0;
#Override
public void execute(Object input) {
if (input != null) {
total += (Integer) input;
}
}
public int getTotal() {
return total;
}
}
Then use this closure as shown below:
public int aggregate(List<Integer> aList) {
AggregateClosure closure = new AggregateClosure();
org.apache.commons.collections.CollectionUtils.forAllDo(aList, closure);
return closure.getTotal();
}
This can be done with reduce using method references reduce(Integer::sum):
Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
.stream()
.reduce(Integer::sum)
.get();
Or without Optional:
Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
.stream()
.reduce(0, Integer::sum);
If you know about the map function, then you know that a map is also can be recursive loop or recursive loop. But obviously you have to reach each element for that. so, I could not work out the Java 8, because some syntax mismatch but wanted a very short so this is what I got.
int sum = 0
for (Integer e : myList) sum += e;
Given that a list can hold any type of object, there is no built in method which allows you to sum all the elements. You could do something like this:
int sum = 0;
for( Integer i : ( ArrayList<Integer> )tt ) {
sum += i;
}
Alternatively you could create your own container type which inherits from ArrayList but also implements a method called sum() which implements the code above.
ArrayList is a Collection of elements (in the form of list), primitive are stored as wrapper class object but at the same time i can store objects of String class as well. SUM will not make sense in that. BTW why are so afraid to use for loop (enhanced or through iterator) anyways?
Or switch to Groovy, it has a sum() function on a collection.
[1,2,3,4,5,6].sum()
http://groovy.codehaus.org/JN1015-Collections
Runs on the same JVM as your java classes.
This link shows three different ways how to sum in java, there is one option that is not in previous answers using Apache Commons Math..
Example:
public static void main(String args []){
List<Double> NUMBERS_FOR_SUM = new ArrayList<Double>(){
{
add(5D);
add(3.2D);
add(7D);
}
};
double[] arrayToSume = ArrayUtils.toPrimitive(NUMBERS_FOR_SUM
.toArray(new Double[NUMBERS_FOR_SUM.size()]));
System.out.println(StatUtils.sum(arrayToSume));
}
See StatUtils api
You can use GNU Trove library:
TIntList tt = new TIntArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
int sum = tt.sum();

Categories

Resources