Sort array and reflect the changes in another array - java

I have an array of doubles, in Java : arr1 which I want to sort. Most probably the first option would be the utility method Arrays.sort(double[]).
The idea is that I want the same changes (e.g. value at index i is interchanged with value at index j in arr1) to be reflected in another array of integers: arr2 (in the sense that the values at the same indexes are changed also in arr2).
Is there a simple way (a trick) to accomplish this in Java? Or the only way is to implement the sorting algorithm by myself?
UPDATE: I see that people recommend replacing the two arrays with one array of objects containing the 2 values (one from arr1 and one from arr2). Wouldn't this bring some efficiency penalties. In other words, isn't it less efficient to sort an array of objects than an array of primitive types (doubles in this case) ?
The data is completely static. It's large (it fits in memory) but static.

Rather than trying to maintain sorted parallel arrays, a cleaner solution would be to create a class that encapsulates both of your data values, and just have one array of objects.
(But to answer your question, there is no built-in way to do this in Java. Implementing your own sort routine that keeps two arrays sorted based on values in one of them would work for a small amount of data that isn't likely to change, but it would be difficult to maintain.)

One solution which is doesn't impact the performance of sorting, ie still O(nlog(n)) time complexity.
Use a map to store array[i] -> i
Sort the array
Iterate over the sorted array, and for each value, use it as a key for the map to retrieve the original index.
Edit: Raihan comment make me look miserable :(

Try it this way....
- Convert this array into ArrayList using the Arrays.asList()
- Create another List Object Reference Variable and assign the same ArrayList object to it, Now any changes to the first ArrayList will be reflected to the Second ArrayList.
Eg:
double[] array = new double[10];
ArrayList<Double> arList_1 = new ArrayList<Double>(Arrays.asList(array));
ArrayList<Double> arList_2 = arList2;
Now for sorting, there are 2 options:
- Use java.lang.Comparable Interface, if you want to sort it in only 1 way.
- Use java.util.Comparator Interface, if you want to sort it in more than 1 way.

Note sure what are you looking for but one other work around could be like this.
Create a map to maintain the relation between arr1 and arr2 elments
Map<Double, Double> myLocalMap<Double, Double>();
for(int ind=0; indx < arr1.length; indx++){
myLocalMap.put(Double.valueOf(arr1[indx]), Double.valueOf(arr2[indx]));
}
Now sort arr1 as you said:
Arrays.sort(arr1);
Once arr1 is sorted, update arr2 as below:
for(int ind=0; indx < arr1.length; indx++){
arr2[indx] = myLocalMap.get(arr1[indx]).doubleValue();
}

Related

Is This The Best Way To "Increase" The Size of An ArrayList?

ArrayList<T> tempArray = new ArrayList<>(size);
I was building a tempArray for my merge sort that will either sort integers or Strings depending on the context. Hence the type T ArrayList.
Then all the sudden I kept running into IndexOutOfBounds errors whenever this was called:
tempArray.set(index, values.get(leftFirst));
After some research I discovered capacity and size don't mean the same thing. So in order to "increase" the size I just added a for loop that runs for size times that adds a null each time:
for (int i = 0; i < size; i++)
tempArray.add(null);
Is this the best solution?
You are trying to use ArrayList as a map, so just switch to Map and hold your keys as integers:
Map<Integer, Object> map = new HashMap<>(size);
map.put(index, values.get(leftFirst));
and then get the index by map.get method:
map.get(index)
Notice if your index start with a million, you will have ~million null values that won't be used. it seems very unnecessary and wrongly implemented.
EDIT
from comments/question, declare your map using T:
Map<Integer, T> map = new HashMap<>(size);
In my opinion the best way is first to create an array of generic type, and after that to create the wrapper with ArrayList.
1.You can see how to create array from generic types here
2.You can see how to create ArrayList from an array here

Best and fastest way to return an array from a map based on some condition

I'm trying to figure out the best and most efficient way for this scenario with a map. It needs to be an array. I've made a dummy example to explain this.
Basically if there is a map that consists of some sandwhich id and and sandwhich details and I only want the ones with lettuce to be in an array.
The problem with arrays is that the size must be known, in this case I do not know how many sandwhiches with lettuces there will be. I could use an array list but I would need to convert it to an array - some copy method which would make this inefficient.
Example:
//Assume that this map is given
Map<Integer, Sandwich> sandwiches = //some method gets all sandwiches
Meal[] meal = new Meal[sandwiches.size()];
for(Map.Entry<Integer, Sandwich> e : sandwiches.entrySet())
{
if(e.getValue().hasLettuce())
meal = new Meal(e.getValue);
}
//mandatory: An array must be returned
return meal;
Use an ArrayList. There's no way to avoid making copies if you don't know how many Meals you'll need, the amortized cost of the copies is cheap, and lists are a better conceptual fit for the problem than arrays anyway. You can call list.toArray(new Meal[0]) to get an array if you really want one.

Copying ArrayList to Array of primitives - is there some bypass to this given this spec?

So I'm to write a simple thing which reads an input file till EOF reached - the file consists of int-double pairs. I'm to calculate the average of all the elements in the second array and finally have both sets of data stored in respective arrays of primitive data types.
Of course the task is easy so the question isn't directly about it - rather, about the array part. As I don't know how many pairs I'll have to store, I use two ArrayLists to store it. The spec strictly points that in the end, however, both ints and doubles have to be store in primitive arrays - and here comes my question. Is there some faster way to do this than just copying the ArrayList to a primitive type array? I can't use an array from the beginning since I don't know the size or even an upper bound and using toArray() also woulnd't work as I have to have primitive int[] and double[] in the end, not objects of Integer[] and Double[].
You should be able to cast from a Double to a primitive double.
Something like:
ArrayList<Double> test = new ArrayList<Double>();
//Get your values into the ArrayList here.
double[] values = new double[test.size()];
for(int i = 0; i < test.size(); i++){
values[i] = test.get(i).doubleValue();
}
As far as I know, there isn't more a "nice" way of doing it than just copying it straight across...
No there is no direct easy way to do it. Converting an ArrayList to a plain array is not that bad as the ArrayList can grow automatically while you should take care for allocating a new array if you have more elements than the one you expected. In the end nothing will change sinche the ArrayList exactly does the same thing but without the need to worry about it.
As for primitive types vs types there is no problem in Java, you can unbox and box them almost for free.
By the way the class ArrayUtil of apache-commons has the method toPrimitive which does this for you.

What is the use of ArrayList<ArrayList<E>>

Can you give any reasonable example for a ArrayList<ArrayList<E>>, such as declaring, initializing, adding elements and iterating them. Is this one of the way to get 2-dimensional Array behavior in Java?
Yes, an ArrayList<ArrayList<E>> is similar to a two-dimensional array of E (E[][]). It has all the common differences between using a List and using arrays in Java (List is a higher-level API, supports resizing, adding elements at arbitrary positions, ...).
You don't treat it any different from a normal List, except that the elements it contains are actually other List objects:
Initialize it:
ArrayList<ArrayList<E>> listOfLists = new ArrayList<ArrayList<E>>();
Iterate over it:
for (ArrayList<E> innerList : listOfLists) {
doSomethingWithInnerList(innerList);
}
Add to it:
ArrayList<E> newInnerList = new ArrayList<E>();
// add stuff to newInnerList
listOfLists.add(newInnerList);
The only thing I want to add to Joachim Sauer's answer is that yes, an ArrayList<ArrayList<E>> can be similar to a two-dimensional array of E (E[][]) with one additional twist (in addition to all the usual differences between one-dimensional arrays and lists):
Using a list of lists, you can make the equivalent of a "jagged" array. Not all of the inner lists need to have the same size(), whereas in a two-dimensional array, all of the "rows" of E[][] by definition have identical lengths. It's "rectangular". A list of lists doesn't have to be rectangular; it can be jagged.
ArrayList is used to hold array of objects. On the other it can have duplicate values. when you need a fast insertion/deletion you can use it. it holds the values in the same order as it is entered into it. For example
List<String> ls= new ArrayList<String>();
ls.add("foo");
ls.add("bar");
for(String val:ls){
System.out.println("Value :" + val);
}

Converting to a column oriented array in Java

Although I have Java in the title, this could be for any OO language.
I'd like to know a few new ideas to improve the performance of something I'm trying to do.
I have a method that is constantly receiving an Object[] array. I need to split the Objects in this array through multiple arrays (List or something), so that I have an independent list for each column of all arrays the method receives.
Example:
List<List<Object>> column-oriented = new ArrayList<ArrayList<Object>>();
public void newObject(Object[] obj) {
for(int i = 0; i < obj.length; i++) {
column-oriented.get(i).add(obj[i]);
}
}
Note: For simplicity I've omitted the initialization of objects and stuff.
The code I've shown above is slow of course. I've already tried a few other things, but would like to hear some new ideas.
How would you do this knowing it's very performance sensitive?
EDIT:
I've tested a few things and found that:
Instead of using ArrayList (or any other Collection), I wrapped an Object[] array in another object to store individual columns. If this array reaches its capacity, I create another array with twice de size and copy the contents from one to another using System.copyArray. Surprisingly (at least for me) this is faster that using ArrayList to store the inner columns...
The answer depends on the data and usage profile. How much data do you have in such collections? What is proportions of reads/writes (adding objects array)? This affects what structure for inner list is better and many other possible optimizations.
The fastest way to copy data is avoid copying at all. If you know that obj array is not modified further by the caller code (this is important condition), one of possible tricks is to implement you custom List class to use as inner list. Internally you will store shared List<Object[]>. Each call we just add new array to that list. Custom inner list class will know which column it represents (let it be n) and when it is asked to give item at position m, it will transpose m and n and query internal structure to get internalArray.get(m)[n]. This implementation is unsafe because of limitation on the caller that is easy to forget about but might be faster under some conditions (however, this might be slower under other).
I would try using LinkedList for the inner list, because it should have better performance for insertions. Maybe wrappping Object arra into collection and using addAll might help as well.
ArrayList may be slow, due to copying of arrays (It uses a similar approach as your self-written collection).
As an alternate solution you could try to simply store the Rows at first and create columns when neccessary. This way, copying of the internal arrays at the list is reduced to a minimum.
Example:
//Notice: You can use a LinkedList for rows, as no index based access is used.
List<Object[]> rows =...
List<List<Object>> columns;
public void processColumns() {
columns = new ArrayList<List<Object>>();
for(Object[] aRow : rows){
while (aRow.size() > columns.size()){
//This ensures that the ArrayList is big enough, so no copying is necessary
List<Object> newColumn = new ArrayList<Object>(rows.size())
columns.add(newColumn);
}
for (int i = 0; i < aRow.length; i++){
columns.get(i).add(aRow[i]);
}
}
}
Depending on the number of columns, it's still possible that the outer list is copying arrays internally, but normal tables contains far more rows than columns, so it should be a small array only.
Use a LinkedList for implementing the column lists. It's grows linearly with the data and is O(1). (If you use ArrayList it has to resize the internal array from time to time).
After collecting the values you can convert that linked lists to arrays. If N is the number of rows you will pass from holding 3*N refs for each list (each LInkedList has prevRef/nextRef/itemRef) to only N refs.
It would be nice to have an array for holding the different column lists, but of course, it's not a big improvement and you can do it only if you know the column count in advance.
Hope it helps!
Edit tests and theory indicate that ArrayList is better in amortized cost, it is, the total cost divided by the number of items processed... so don't follow my 'advice' :)

Categories

Resources