I am trying to create a cartesian product method in java that accepts sets as arguments and returns a set pair. The code I have coverts the argumented sets to arrays and then does the cartesian product but i can't add it back to the set pair that i want to return. Is there an easier way to do this? Thanks in advance.
public static <S, T> Set<Pair<S, T>> cartesianProduct(Set<S> a, Set<T> b) {
Set<Pair<S, T>> product = new HashSet<Pair<S, T>>();
String[] arrayA = new String[100];
String[] arrayB= new String[100];
a.toArray(arrayA);
b.toArray(arrayB);
for(int i = 0; i < a.size(); i++){
for(int j = 0; j < b.size(); j++){
product.add(arrayA[i],arrayB[j]);
}
}
return product;
}
this looks simpler,
public static <S, T> Set<Pair<S, T>> cartesianProduct(Set<S> a, Set<T> b) {
Set<Pair<S, T>> product = new HashSet<Pair<S, T>>();
for(S s : a) {
for(T t : b) {
product.add(new ImmutablePair<S, T>(s,t));
}
}
return product;
}
Assuming you're using Pair from Apache Commons, then I think you want the add to be
product.add(Pair.of(arrayA[i],arrayB[j]));
There's no add method for sets that takes two arguments. You have to create the Pair to add to the set. If that doesn't compile, try
product.add(Pair<S,T>.of(arrayA[i],arrayB[j]));
Also, I'm assuming you meant S and T for your arrays, instead of String. There's no reason to preallocate a certain number of elements. Furthermore, the way you've written it, if there are more than 100 elements in either set, toArray will return an all new array with the desired size, but you're not using the function result so that array will be lost. I'd prefer:
S[] arrayA = a.toArray(new S[0]);
T[] arrayB = b.toArray(new T[0]);
The zero-length arrays are just "dummies" whose purpose is to get toArray to return arrays with the correct element type, instead of Object[].
EDIT: Using an enhanced for loop is a lot better than using arrays. See Camilo's answer.
Related
I have a class mapper that is supposed to apply any object that implements the Function interface to an array of type D, and return an array of type R.
The problem is that Java does not let me use "new R[]," and so far I've struggled to figure out a way to create an R array from scratch. I currently am attempting to use the Array.newInstance method, but can't find a way to store the class type of R in a Class variable.
public class Mapper {
/**
* applies passed function to each object of type D in array
* #param function
* #param array
* #return array of type r and length array.length
*/
public static <R, D> R[] map(Function<R, D> function, D[] array) {
ArrayList<R> list = new ArrayList<R>();
//apply function to each variable
//add rs into object array
for( int i = 0; i < array.length; i++ ) {
R r = function.apply( array[i] );
list.add( r );
}
Class<R> clazz = list.get(0).getClass();
return (R[])Array.newInstance(clazz, list.size());
}
}
What can I do properly attain a class value at runtime for the generic type R, or otherwise return the objects in ArrayList as an R[]?
The problem you are facing is related to Java generics type erasure. Since all generic types are erased at runtime, Java has to make trade offs to guarantee type safety.
The problem with generic arrays is that Java would not be able to guarantee that type safety, you can find a good example about this here. In short, generic array creation is not allowed.
To keep most of your original code, you can use Object[]:
public static <D, R> Object[] map(Function<D, R> function, D[] array) {
List<R> list = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
R r = function.apply(array[i]);
list.add(r);
}
return list.toArray(new Object[0]); // no generic array creation allowed!
}
But, that´s why most people stick to lists, as it is way easier to operate with them when generics are involved:
public static <D, R> List<R> map(Function<D, R> function, List<D> array) {
List<R> list = new ArrayList<>();
for (D d : array) {
list.add(function.apply(d));
}
return list;
}
And the good part about this is that you can still convert it to an array afterwards when the concrete type is known:
List<String> strings = List.of("Test1", "Test2");
String[] array = map(String::toLowerCase, strings).toArray(new String[0]);
The cleanest way to do this is to simply pass a Class object to the function. Also, it seems like you have the order of the type parameters to Function reversed -- the first type parameter should be the input type and the second should be the result type. Something like this should get you closer to what you want:
public static <R, D> R[] map(Function<D, R> function, D[] array, Class<R> clazz) {
R[] result = (R[]) Array.newInstance(clazz, array.length);
// apply function to each variable and add return value to the result array
for( int i = 0; i < array.length; i++ ) {
result[i] = function.apply(array[i]);
}
return result;
}
(I'd also suggest reversing the order of the type parameters to your method, to be consistent with the built-in reflection classes like Function.)
I have an array. Lets say this array is called numberCards. it is defined as {0,1,2,5,6,10,42} I want to talk an array which consits of indices (2-4 (inclusive)) and indices 7 and 8. Is there a way to do this in as few lines as possible?
You can do this to extract a sub set of values or the change the order.
public static <T> T[] select(T[] ts, int... indecies) {
T[] copy = (T[]) new Object[indecies.length];
for (int i = 0; i < indecies.length; i++)
copy[i] = ts[indecies[i]];
return copy;
}
I have a multidimensional array with double values that I would like to sort..
//declare array
standingsB = new Double[10][2];
//populate array from the temparray created during read from file
arryLgt = 0;
for (int row = 0; row < standingsB.length; row++){
for (int column = 0; column < standingsB[row].length; column++) {
standingsB[row][column] = Double.parseDouble(tempStandingsArray[arryLgt]);
arryLgt = arryLgt + 1;
}
}
The array has values such as [1.5,7.0] [4.2,4.0] etc...
For the next part I don't really know how it works but from reading other articles here this is the best as I can copy without knowledge
Arrays.sort(standingsB, new Comparator<Double[]>() {
#Override
public int compare(Double[] s1, Double[] s2) {
compare(s1, s2);
}
});
The above fails to compile (with missing return statement) which is to be expected as I have no idea on how to use the Arrays.sort with a comparator. But I'm not even sure if I'm on the right page being as new to Java (and programing in general) as I am.
Thanks for looking!
You're pretty close. Your comparator will depend on what order you want your results in. Let's say you want the rows to be sorted in the natural order of the first element in each row. Then your code would look like:
Arrays.sort(standingsB, new Comparator<Double[]>() {
public int compare(Double[] s1, Double[] s2) {
if (s1[0] > s2[0])
return 1; // tells Arrays.sort() that s1 comes after s2
else if (s1[0] < s2[0])
return -1; // tells Arrays.sort() that s1 comes before s2
else {
/*
* s1 and s2 are equal. Arrays.sort() is stable,
* so these two rows will appear in their original order.
* You could take it a step further in this block by comparing
* s1[1] and s2[1] in the same manner, but it depends on how
* you want to sort in that situation.
*/
return 0;
}
}
};
I think the answer provided by #Tap doesn't fulfill the askers question to 100%. As described, the array is sorted for its value at the first index only. The result of sorting {{2,0},{1,2},{1,1}} would be {{1,2},{1,1},{2,0}} not {{1,1},{1,2},{2,0}}, as expected. I've implemented a generic ArrayComparator for all types implementing the Comparable interface and released it on my blog:
public class ArrayComparator<T extends Comparable<T>> implements Comparator<T[]> {
#Override public int compare(T[] arrayA, T[] arrayB) {
if(arrayA==arrayB) return 0; int compare;
for(int index=0;index<arrayA.length;index++)
if(index<arrayB.length) {
if((compare=arrayA[index].compareTo(arrayB[index]))!=0)
return compare;
} else return 1; //first array is longer
if(arrayA.length==arrayB.length)
return 0; //arrays are equal
else return -1; //first array is shorter
}
}
With this ArrayComparator you can sort multi-dimensional arrays:
String[][] sorted = new String[][]{{"A","B"},{"B","C"},{"A","C"}};
Arrays.sort(sorted, new ArrayComparator<>());
Lists of arrays:
List<String[]> sorted = new ArrayList<>();
sorted.add(new String[]{"A","B"});
sorted.add(new String[]{"B","C"});
sorted.add(new String[]{"A","C"});
sorted.sort(new ArrayComparator<>());
And build up (Sorted)Maps easily:
Map<String[],Object> sorted = new TreeMap<>(new ArrayComparator<>());
sorted.put(new String[]{"A","B"}, new Object());
sorted.put(new String[]{"B","C"}, new Object());
sorted.put(new String[]{"A","C"}, new Object());
Just remember, the generic type must implement the Comparable interface.
Solution with lambda sorting array of int[][] contests example :
Arrays.sort(contests, (a, b)->Integer.compare(b[0], a[0]));
Arrays.sort() expects a single dimensional array while in your case you are trying to pass a multidimensional array.
eg
Double[] d = {1.0,5.2,3.2};
Then you use Arrays.sort(d) since the sort can work on the primitive types or the wrapper types.
I'm brushing up on my data structure skills. I found a great free book online called Open Data Structures in Java. After reading through it, I'm trying to create all the stated data structures with the code provided so I can instill them in to my memory.
I ran in to an "error" and for the life of me I can't figure it out: in the resize() method for the ArrayStack (section 2.1.2), there is the line of code - T[] b = newArray(Math.max(n*2,1));. The point of this is so the array, which contains the elements, is neither too small or too large. If I use this line of code I get the following error message from Eclipse:
The method newArray(int) is undefined for the type ArrayStack<T>.
So, I'm thinking that it must have been a "typo" and what was meant was "new Array". But fixing that leaves me with the following error message from Eclipse:
Type mismatch: cannot convert from Array to T[].
I don't understand what I'm missing or doing wrong. So to sum up my question, how do you declare and instantiate a new generic array, particularly at a fixed size?
Given the class of T, let's call it klass...
For a one-dimensional array of length n:
T[] arr = (T[]) Array.newInstance(klass, n)
For a two-dimensional array of length n x m:
T[][] 2dArr = (T[][]) Array.newInstance(klass, n, m)
The above are actually two different functions, one takes an int argument and the second takes an int... argument, which you can also pass as an array. Both return an Object for which you need an unchecked cast.
If you want a jagged array of length n, second dimension undetermined, you will have to get the class of T[], let's call it klass2, and then do
T[][] 2dArr2 = (T[][]) Array.newInstance(klass2, n)
This is why you also need to pass in a type to collection.toArray(T[] arr), otherwise you get an Object[] for the vanilla toArray() method because it doesn't know the type.
What you would like is:
void resize() {
T[] b = new T[Math.max(n*2,1)];
for (int i = 0; i < n; i++) {
b[i] = a[i];
}
a = b;
}
But that does not work because T is not actually known at runtime, and it would have to be. However this can be written with a generic-safe constructor.
void resize() {
T[] b = (T[]) Array.newInstance( a.getClass().getComponentType(),
Math.max(n*2,1) );
for (int i = 0; i < n; i++) {
b[i] = a[i];
}
a = b;
}
It appears that the author meant to have a method, newArray in that class:
void T[] newArray(int size) {
return (T[]) Array.newInstance( a.getClass().getComponentType(), size);
}
Java does not make this a simple matter. Because of type erasure the class of T is not available at runtime (which is when you need to determine what type of array to create).
However, since you already have an array (a), you can use reflection to create a new array of that type.
It will look something like this:
import java.lang.reflect.Array;
public class Test {
public static void main(String args[]) throws Exception {
Object array[] = new Object[5];
array = resizeArray(array, 10);
for (Object o : array) {
System.out.println(o);
}
}
public static <T>
T[] resizeArray(T[] a, int newSize) throws Exception {
T[] b = (T[]) Array.newInstance(a.getClass().getComponentType(),
newSize);
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
return b;
}
}
I have a matrix of W of large row and column dimension. Each of the row represents feature values(filled with double value).And the matrix is constructed as:
Hashmap<Integer,Arraylist<Double>> W = new Hashmap<Integer,Arraylist<Double>>();
While making computation, I need to take certain portion of each of the rows and update them in matrix. I looked for subList method in Arraylist. But the problem is it returns only list but I am in need of arraylist. Because many of the methods that I have already implemented take <Arraylist> as argument. So what can be the solution for this case?
Example
w1 = [1,3 ,4,6,9,1,34,5,21,5,2,5,1]
w11 = [1,3,4]
w11 = w11 +1 = [2,4,5]
This changes w1 to = [2,4 ,5,6,9,1,34,5,21,5,2,5,1]
I looked for subList method in Arraylist.But the problem is it returns only list but i am in need of arraylist
That is not a problem at all. In fact, you should change your code to use List wherever possible.
A List is an interface which concrete types such as the ArrayList implement. The below is perfectly valid:
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
I recommend changing your W to this:
Hashmap<Integer, List<Double>> W = new Hashmap<Integer, List<Double>>();
You could subclass ArrayList to provide a view of a slice of another ArrayList. Like this:
class ArrayListSlice<E> extends ArrayList<E> {
private ArrayList<E> backing_list;
private int start_idx;
private int len;
ArrayListSlice(ArrayList<E> backing_list, int start_idx, int len) {
this.backing_list = backing_list;
this.start_idx = start_idx;
this.len = len;
}
public E get(int index) {
if (index < 0 || idx >= len) throw new IndexOutOfBoundsException();
return backing_list.get(start_idx + index);
}
... set, others? ...
}
Then you can do w11 = new ArrayListSlice<Double>(w1, 0, 3). Any operations on w11 will appear in w1, assuming you implement set correctly.
You will probably need to implement most the methods of ArrayList to make this work. Some may work if they just rely on others, but that's hard to tell from the spec.