Java Array Sort descending? - java
Is there any EASY way to sort an array in descending order like how they have a sort in ascending order in the Arrays class?
Or do I have to stop being lazy and do this myself :[
You could use this to sort all kind of Objects
sort(T[] a, Comparator<? super T> c)
Arrays.sort(a, Collections.reverseOrder());
Arrays.sort() cannot be used directly to sort primitive arrays in descending order. If you try to call the Arrays.sort() method by passing reverse Comparator defined by Collections.reverseOrder() , it will throw the error
no suitable method found for sort(int[],comparator)
That will work fine with 'Array of Objects' such as Integer array but will not work with a primitive array such as int array.
The only way to sort a primitive array in descending order is, first sort the array in ascending order and then reverse the array in place. This is also true for two-dimensional primitive arrays.
for a list
Collections.sort(list, Collections.reverseOrder());
for an array
Arrays.sort(array, Collections.reverseOrder());
You can use this:
Arrays.sort(data, Collections.reverseOrder());
Collections.reverseOrder() returns a Comparator using the inverse natural order. You can get an inverted version of your own comparator using Collections.reverseOrder(myComparator).
an alternative could be (for numbers!!!)
multiply the Array by -1
sort
multiply once again with -1
Literally spoken:
array = -Arrays.sort(-array)
without explicit comparator:
Collections.sort(list, Collections.reverseOrder());
with explicit comparator:
Collections.sort(list, Collections.reverseOrder(new Comparator()));
It's not directly possible to reverse sort an array of primitives (i.e., int[] arr = {1, 2, 3};) using Arrays.sort() and Collections.reverseOrder() because those methods require reference types (Integer) instead of primitive types (int).
However, we can use Java 8 Stream to first box the array to sort in reverse order:
// an array of ints
int[] arr = {1, 2, 3, 4, 5, 6};
// an array of reverse sorted ints
int[] arrDesc = Arrays.stream(arr).boxed()
.sorted(Collections.reverseOrder())
.mapToInt(Integer::intValue)
.toArray();
System.out.println(Arrays.toString(arrDesc)); // outputs [6, 5, 4, 3, 2, 1]
First you need to sort your array using:
Collections.sort(myArray);
Then you need to reverse the order from ascending to descending using:
Collections.reverse(myArray);
Java 8:
Arrays.sort(list, comparator.reversed());
Update:
reversed() reverses the specified comparator. Usually, comparators order ascending, so this changes the order to descending.
For array which contains elements of primitives if there is org.apache.commons.lang(3) at disposal easy way to reverse array (after sorting it) is to use:
ArrayUtils.reverse(array);
When an array is a type of Integer class then you can use below:
Integer[] arr = {7, 10, 4, 3, 20, 15};
Arrays.sort(arr, Collections.reverseOrder());
When an array is a type of int data type then you can use below:
int[] arr = {7, 10, 4, 3, 20, 15};
int[] reverseArr = IntStream.rangeClosed(1, arr.length).map(i -> arr[arr.length-i]).toArray();
I don't know what your use case was, however in addition to other answers here another (lazy) option is to still sort in ascending order as you indicate but then iterate in reverse order instead.
For discussions above, here is an easy example to sort the primitive arrays in descending order.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] nums = { 5, 4, 1, 2, 9, 7, 3, 8, 6, 0 };
Arrays.sort(nums);
// reverse the array, just like dumping the array!
// swap(1st, 1st-last) <= 1st: 0, 1st-last: nums.length - 1
// swap(2nd, 2nd-last) <= 2nd: i++, 2nd-last: j--
// swap(3rd, 3rd-last) <= 3rd: i++, 3rd-last: j--
//
for (int i = 0, j = nums.length - 1, tmp; i < j; i++, j--) {
tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
// dump the array (for Java 4/5/6/7/8/9)
for (int i = 0; i < nums.length; i++) {
System.out.println("nums[" + i + "] = " + nums[i]);
}
}
}
Output:
nums[0] = 9
nums[1] = 8
nums[2] = 7
nums[3] = 6
nums[4] = 5
nums[5] = 4
nums[6] = 3
nums[7] = 2
nums[8] = 1
nums[9] = 0
Another solution is that if you're making use of the Comparable interface you can switch the output values which you had specified in your compareTo(Object bCompared).
For Example :
public int compareTo(freq arg0)
{
int ret=0;
if(this.magnitude>arg0.magnitude)
ret= 1;
else if (this.magnitude==arg0.magnitude)
ret= 0;
else if (this.magnitude<arg0.magnitude)
ret= -1;
return ret;
}
Where magnitude is an attribute with datatype double in my program. This was sorting my defined class freq in reverse order by it's magnitude. So in order to correct that, you switch the values returned by the < and >. This gives you the following :
public int compareTo(freq arg0)
{
int ret=0;
if(this.magnitude>arg0.magnitude)
ret= -1;
else if (this.magnitude==arg0.magnitude)
ret= 0;
else if (this.magnitude<arg0.magnitude)
ret= 1;
return ret;
}
To make use of this compareTo, we simply call Arrays.sort(mFreq) which will give you the sorted array freq [] mFreq.
The beauty (in my opinion) of this solution is that it can be used to sort user defined classes, and even more than that sort them by a specific attribute. If implementation of a Comparable interface sounds daunting to you, I'd encourage you not to think that way, it actually isn't. This link on how to implement comparable made things much easier for me. Hoping persons can make use of this solution, and that your joy will even be comparable to mine.
For 2D arrays to sort in descending order you can just flip the positions of the parameters
int[][] array= {
{1, 5},
{13, 1},
{12, 100},
{12, 85}
};
Arrays.sort(array, (a, b) -> Integer.compare(a[1], b[1])); // for ascending order
Arrays.sort(array, (b, a) -> Integer.compare(a[1], b[1])); // for descending order
Output for descending
12, 100
12, 85
1, 5
13, 1
You could use stream operations (Collections.stream()) with Comparator.reverseOrder().
For example, say you have this collection:
List<String> items = new ArrayList<>();
items.add("item01");
items.add("item02");
items.add("item03");
items.add("item04");
items.add("item04");
To print the items in their "natural" order you could use the sorted() method (or leave it out and get the same result):
items.stream()
.sorted()
.forEach(item -> System.out.println(item));
Or to print them in descending (reverse) order, you could use the sorted method that takes a Comparator and reverse the order:
items.stream()
.sorted(Comparator.reverseOrder())
.forEach(item -> System.out.println(item));
Note this requires the collection to have implemented Comparable (as do Integer, String, etc.).
There is a lot of mess going on here - people suggest solutions for non-primitive values, try to implement some sorting algos from the ground, give solutions involving additional libraries, showing off some hacky ones etc. The answer to the original question is 50/50. For those who just want to copy/paste:
// our initial int[] array containing primitives
int[] arrOfPrimitives = new int[]{1,2,3,4,5,6};
// we have to convert it into array of Objects, using java's boxing
Integer[] arrOfObjects = new Integer[arrOfPrimitives.length];
for (int i = 0; i < arrOfPrimitives.length; i++)
arrOfObjects[i] = new Integer(arrOfPrimitives[i]);
// now when we have an array of Objects we can use that nice built-in method
Arrays.sort(arrOfObjects, Collections.reverseOrder());
arrOfObjects is {6,5,4,3,2,1} now. If you have an array of something other than ints - use the corresponding object instead of Integer.
Simple method to sort an int array descending:
private static int[] descendingArray(int[] array) {
Arrays.sort(array);
int[] descArray = new int[array.length];
for(int i=0; i<array.length; i++) {
descArray[i] = array[(array.length-1)-i];
}
return descArray;
}
Adding my answer in here for a couple of different scenarios
For an Array
Arrays.sort(a, Comparator.reverseOrder());
FWIW Lists
Lists.reverse(a);
Any and all Collections
Collections.reverse(a);
I know that this is a quite old thread, but here is an updated version for Integers and Java 8:
Arrays.sort(array, (o1, o2) -> o2 - o1);
Note that it is "o1 - o2" for the normal ascending order (or Comparator.comparingInt()).
This also works for any other kinds of Objects. Say:
Arrays.sort(array, (o1, o2) -> o2.getValue() - o1.getValue());
This worked for me:
package doublearraysort;
import java.util.Arrays;
import java.util.Collections;
public class Gpa {
public static void main(String[] args) {
// initializing unsorted double array
Double[] dArr = new Double[] {
new Double(3.2),
new Double(1.2),
new Double(4.7),
new Double(3.3),
new Double(4.6),
};
// print all the elements available in list
for (double number : dArr) {
System.out.println("GPA = " + number);
}
// sorting the array
Arrays.sort(dArr, Collections.reverseOrder());
// print all the elements available in list again
System.out.println("The sorted GPA Scores are:");
for (double number : dArr) {
System.out.println("GPA = " + number);
}
}
}
Output:
GPA = 3.2
GPA = 1.2
GPA = 4.7
GPA = 3.3
GPA = 4.6
The sorted GPA Scores are:
GPA = 4.7
GPA = 4.6
GPA = 3.3
GPA = 3.2
GPA = 1.2
public double[] sortArrayAlgorithm(double[] array) { //sort in descending order
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (array[i] >= array[j]) {
double x = array[i];
array[i] = array[j];
array[j] = x;
}
}
}
return array;
}
just use this method to sort an array of type double in descending order, you can use it to sort arrays of any other types(like int, float, and etc) just by changing the "return type", the "argument type" and the variable "x" type to the corresponding type. you can also change ">=" to "<=" in the if condition to make the order ascending.
Another way with Comparator
import java.util.Arrays;
import java.util.Comparator;
...
Integer[] aInt = {6,2,3,4,1,5,7,8,9,10};
Arrays.sort(aInt, Comparator.reverseOrder() );
It's good sometimes we practice over an example, here is a full one:
sortdesc.java
import java.util.Arrays;
import java.util.Collections;
class sortdesc{
public static void main(String[] args){
// int Array
Integer[] intArray=new Integer[]{
new Integer(15),
new Integer(9),
new Integer(16),
new Integer(2),
new Integer(30)};
// Sorting int Array in descending order
Arrays.sort(intArray,Collections.reverseOrder());
// Displaying elements of int Array
System.out.println("Int Array Elements in reverse order:");
for(int i=0;i<intArray.length;i++)
System.out.println(intArray[i]);
// String Array
String[] stringArray=new String[]{"FF","PP","AA","OO","DD"};
// Sorting String Array in descending order
Arrays.sort(stringArray,Collections.reverseOrder());
// Displaying elements of String Array
System.out.println("String Array Elements in reverse order:");
for(int i=0;i<stringArray.length;i++)
System.out.println(stringArray[i]);}}
compiling it...
javac sortdec.java
calling it...
java sortdesc
OUTPUT
Int Array Elements in reverse order:
30
16
15
9
2
String Array Elements in reverse order:
PP
OO
FF
DD
AA
If you want to try an alphanumeric array...
//replace this line:
String[] stringArray=new String[]{"FF","PP","AA","OO","DD"};
//with this:
String[] stringArray=new String[]{"10FF","20AA","50AA"};
you gonna get the OUTPUT as follow:
50AA
20AA
10FF
source
There is a way that might be a little bit longer, but it works fine. This is a method to sort an int array descendingly.
Hope that this will help someone ,,, some day:
public static int[] sortArray (int[] array) {
int [] sortedArray = new int[array.length];
for (int i = 0; i < sortedArray.length; i++) {
sortedArray[i] = array[i];
}
boolean flag = true;
int temp;
while (flag) {
flag = false;
for (int i = 0; i < sortedArray.length - 1; i++) {
if(sortedArray[i] < sortedArray[i+1]) {
temp = sortedArray[i];
sortedArray[i] = sortedArray[i+1];
sortedArray[i+1] = temp;
flag = true;
}
}
}
return sortedArray;
}
I had the below working solution
public static int[] sortArrayDesc(int[] intArray){
Arrays.sort(intArray); //sort intArray in Asc order
int[] sortedArray = new int[intArray.length]; //this array will hold the sorted values
int indexSortedArray = 0;
for(int i=intArray.length-1 ; i >= 0 ; i--){ //insert to sortedArray in reverse order
sortedArray[indexSortedArray ++] = intArray [i];
}
return sortedArray;
}
Here is how I sorted a primitive type int array.
int[] intArr = new int[] {9,4,1,7};
Arrays.sort(nums);
Collections.reverse(Arrays.asList(nums));
Result:
[1, 4, 7, 9]
I know many answers are here, but still thinks , none of them tried using core java.
And using collection api , you will end up wasting so much memory and reseduals.
here is a try with pure core concepts , and yes this may be better way if you are more concerned about memory footprints.
int[] elements = new int [] {10,999,999,-58,548,145,255,889,1,1,4,5555,0,-1,-52};
//int[] elements = null;
if(elements != null && elements.length >1)
{
int max = 0, index = 0;
for(int i =0;i<elements.length;i++)//find out what is Max
{
if(elements[i] > max)
{
max = elements[i];
index = i;
}
}
elements[index] = elements[0];//Swap the places
elements[0] = max;
for(int i =0;i < elements.length;i++)//loop over element
{
for(int j = i+1;j < elements.length;j++)//loop to compare the elements
{
if(elements[j] > elements[i])
{
max = elements[j];
elements[j] = elements[i];
elements[i] = max;
}
}
}
}//i ended up using three loops and 2 extra variables
System.out.println(Arrays.toString(elements));//if null it will print null
// still love to learn more, please advise if we can do it better.
Love to learn from you too !
Related
Sorting an ArrayList of arrays in java
I'd like to know if you know a way to sort an ArrayList of arrays in Java. I have a function that gives a score between 0 and 1 to a specific array. And I'd like to sort the ArrayList so that arrays having the highest score come first. public double evaluate(int[] toEvaluate) { double result = 0.0; for (int i = 0; i < toEvaluate.length; i++) { result += table[i][casesMap.get(toEvaluate[i])]; } return result / toEvaluate.length; } Any ideas ?
You should use Collections.sort() together with a custom Comparator: List<Integer[]> arrays = new ArrayList<>(); arrays.add(new Integer[]{1, 2}); arrays.add(new Integer[]{3, 4}); Collections.sort(arrays, new Comparator<Integer[]>() { public int compare(Integer[] a, Integer[] b) { return 1; // FIX this according to your needs } }); compare() above is just a stub, you should implement it according to the documentation and it could be replaced with a lambda expression. In the code above that would be: Collections.sort(arrays, (a, b) -> 1).
You have to write a Comparator and compare method override where you can use your function to calculate comp value #Override public int compare(Integer[] o1, Integer[] o2) { int o1Number=ratingFunction(o1) ; int o2Number=ratingFunction(o2) ; int cmp=o1Number.compareTo(o2Number); return cmp; }
You can either use comparator to sort list in descending order or you can use Collections sort method and then use reverse method to make it descending order, something like this : List<Integer> numberList =new ArrayList<Integer>(); numberList.add(3); numberList.add(1); numberList.add(2); //before sort for (Integer integer : numberList) { System.out.println(integer); } //sorting Collections.sort(numberList); Collections.reverse(numberList); //after sort for (Integer integer : numberList) { System.out.println(integer); }
You might want to use stream api for that. So let's say we have the scoring function (I simplified it for the sake of example). public static double evaluate(int[] arr){ return Arrays.stream(arr).sum() / arr.length; } Now we can use it with Comparator.comparing method: List<int[]> list = Arrays.asList(new int[]{4, 5}, new int[]{2, 3}, new int[]{0, 1}); List<int[]> sorted = list.stream(). sorted(Comparator.comparing(Main::evaluate)). collect(Collectors.toList()); sorted.forEach(x -> System.out.println(Arrays.toString(x))); The idea behind the code is quite simple, you provide a comparator which defines how to sort int[] arrays. I hope this helps.
An efficient way to convert List<Integer> to int[] ( array ) without iteration
public static int[] convertListToArray(List<Integer> listResult) { int[] result = new int[listResult.size()]; int i= 0; for (int num : listResult) { result[i++] = num; } return result; } Is there an efficient way to convert List to array without iterating List explicitly ? Maybe it is possible by using methods like: Arrays.copyOf(int [] origin , int newLength ); System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length); I know that there is a solution described here. However, I particularly interested in an efficient way of converting List<Integer> to int[]
Given the need to convert from Integer to int, I don't think you're going to find something more efficient than what you have, if I assume you're talking about runtime efficiency. You might find converting to Integer[] first and then looping might be more efficient (below), but you might not, too. You'd have to test it in your specific scenario and see. Here's that example: int size = listResult.size(); int[] result = new int[size]; Integer[] temp = listResult.toArray(new Integer[size]); for (int n = 0; n < size; ++n) { result[n] = temp[n]; }
If efficiency is your primary concern, I think you can use your solution and make it more efficient by using an indexed for loop on the listResult if it is RandomAccess. However this makes the code much less readable, and you'd have to benchmark it for your use cases to see if it is more efficient. public static int[] convertListToArray(List<Integer> listResult) { int size = listResult.size(); int[] result = new int[size]; if (listResult instanceof RandomAccess) { for (int i = 0; i < size; i++) { result[i] = listResult.get(i); } } else { int i = 0; for (int num : listResult) { result[i++] = num; } } return result; } If you use Java 8 and would like to write less code you can use the Streams library. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); int[] array = list.stream().mapToInt(i -> i).toArray(); If you are open to using a third party library, you can Eclipse Collections as follows. MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5); int[] array = list.collectInt(i -> i).toArray(); The following is slightly more code, but is the most efficient solution I could come up with using Eclipse Collections. MutableList<Integer> list = Lists.mutable.with(1, 2, 3, 4, 5); int[] array = new int[list.size()]; list.forEachWithIndex((each, index) -> array[index] = each); If you need to use the java.util.List interface, the ListIterate utility class can be used from Eclipse Collections. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); int[] array = new int[list.size()]; ListIterate.forEachWithIndex(list, (each, index) -> array[index] = each); The ListIterate utility will use different iteration code for RandomAccess lists and non-RandomAccess lists. The most efficient thing to do would be to change the List<Integer> to a MutableIntList in Eclipse Collections or another library that has support for primitive collections. Note: I am a committer for Eclipse Collections.
In Java 8: int[] anArray = list.stream() .filter(Objects::nonNull) .mapToInt(Integer::intValue) .toArray();
There is efficient way you could do this Java. However, this could open room for someone to create the generic function (depend on demand). Just like this sample i wrote, I suggest you do the same to the specific knowledge of your program. // Generic function to convert set to list public static <T> ArrayList<T> convertSetToList(Set<T> set) { // create an empty list ArrayList<T> list = new ArrayList<>(); // push each element in the set into the list for (T t : set) list.add(t); // return the list return list; }
Java element-wise sum 2 arrays
Given that I have two arrays in Java, A and B I want to add the elements, element-wise, which results in a sum array. Doing this implicitly with a loop is easy but I was wondering if there was a more elegant solution, perhaps with the guava collections or build in java utils. Or perhaps a python-ish way which makes is easy with list comprehensions. Example: A = [2,6,1,4] B = [2,1,4,4] sum = [4,7,5,8]
You can do it like this: private void sum() { int a[] = {2, 6, 1, 4}; int b[] = {2, 1, 4, 4}; int result[] = new int[a.length]; Arrays.setAll(result, i -> a[i] + b[i]); } This will first create int result[] of the correct size. Then with Java 8, released yesterday, the easy part comes: You can do an Arrays.setAll(int[] array, IntUnaryOperator); As IntUnaryOperator you can create a lambda mapping the index to the result, in here we choose to map i to a[i] + b[i], which exactly produces our sum. For very big arrays we can even use Arrays.parallelSetAll
You can use java8 stream and operation on array like this: //in this example a[] and b[] are same length int[] a = ... int[] b = ... int[] result = new int[a.length]; IntStream.range(0, a.length) .forEach(i -> result[i] = a[i] + b[i]); The answer in java8
Java, find intersection of two arrays
I have already read a few other stack overflow threads on this: to find the intersection of two multisets in java How do I get the intersection between two arrays as a new array? public static int[] intersection (int [] x, int numELementsInX, int [] y, int numElementsInY) { I am trying to examine two arrays as well as their number of elements (numElementsInX and numElementsInY), and return a new array which contains the common values of array x and y. Their intersection. Example,if x is{1,3,5,7,9}and y is{9,3,9,4} then intersection(x, 5, y, 4} should return {3, 9} or {9, 3} I've read I need to use the LCS algorithm. Can anyone give me an example as to how to do this? Both the array and values in array are initialized and generated in another method, then passed into intersection. Any help/clarification is appreciated. EDIT CODE for (int i=0; i<numElementsInX; i++){ for (int j=0; j<numElementsInY; j++){ if (x[j]==x[i]) { //how to push to new array?; } else{ } } }
The simplest solution would be to use sets, as long as you don't care that the elements in the result will have a different order, and that duplicates will be removed. The input arrays array1 and array2 are the Integer[] subarrays of the given int[] arrays corresponding to the number of elements that you intend to process: Set<Integer> s1 = new HashSet<Integer>(Arrays.asList(array1)); Set<Integer> s2 = new HashSet<Integer>(Arrays.asList(array2)); s1.retainAll(s2); Integer[] result = s1.toArray(new Integer[s1.size()]); The above will return an Integer[], if needed it's simple to copy and convert its contents into an int[].
If you are fine with java-8, then the simplest solution I can think of is using streams and filter. An implementation is as follows: public static int[] intersection(int[] a, int[] b) { return Arrays.stream(a) .distinct() .filter(x -> Arrays.stream(b).anyMatch(y -> y == x)) .toArray(); }
General test The answers provide several solutions, so I decided to figure out which one is the most effective. Solutions HashSet based by Óscar López Stream based by Bilesh Ganguly Foreach based by Ruchira Gayan Ranaweera HashMap based by ikarayel What we have Two String arrays that contain 50% of the common elements. Every element in each array is unique, so there are no duplicates Testing code public static void startTest(String name, Runnable test){ long start = System.nanoTime(); test.run(); long end = System.nanoTime(); System.out.println(name + ": " + (end - start) / 1000000. + " ms"); } With use: startTest("HashMap", () -> intersectHashMap(arr1, arr2)); startTest("HashSet", () -> intersectHashSet(arr1, arr2)); startTest("Foreach", () -> intersectForeach(arr1, arr2)); startTest("Stream ", () -> intersectStream(arr1, arr2)); Solutions code: HashSet public static String[] intersectHashSet(String[] arr1, String[] arr2){ HashSet<String> set = new HashSet<>(Arrays.asList(arr1)); set.retainAll(Arrays.asList(arr2)); return set.toArray(new String[0]); } Stream public static String[] intersectStream(String[] arr1, String[] arr2){ return Arrays.stream(arr1) .distinct() .filter(x -> Arrays.asList(arr2).contains(x)) .toArray(String[]::new); } Foreach public static String[] intersectForeach(String[] arr1, String[] arr2){ ArrayList<String> result = new ArrayList<>(); for(int i = 0; i < arr1.length; i++){ for(int r = 0; r < arr2.length; r++){ if(arr1[i].equals(arr2[r])) result.add(arr1[i]); } } return result.toArray(new String[0]); } HashMap public static String[] intersectHashMap(String[] arr1, String[] arr2){ HashMap<String, Integer> map = new HashMap<>(); for (int i = 0; i < arr1.length; i++) map.put(arr1[i], 1); ArrayList<String> result = new ArrayList<>(); for(int i = 0; i < arr2.length; i++) if(map.containsKey(arr2[i])) result.add(arr2[i]); return result.toArray(new String[0]); } Testing process Let's see what happens if we give the methods an array of 20 elements: HashMap: 0.105 ms HashSet: 0.2185 ms Foreach: 0.041 ms Stream : 7.3629 ms As we can see, the Foreach method does the best job. But the Stream method is almost 180 times slower. Let's continue the test with 500 elements: HashMap: 0.7147 ms HashSet: 4.882 ms Foreach: 7.8314 ms Stream : 10.6681 ms In this case, the results have changed dramatically. Now the most efficient is the HashMap method. Next test with 10 000 elements: HashMap: 4.875 ms HashSet: 316.2864 ms Foreach: 505.6547 ms Stream : 292.6572 ms The fastest is still the HashMap method. And the Foreach method has become quite slow. Results If there are < 50 elements, then it is best to use the Foreach method. He strongly breaks away in speed in this category. In this case, the top of the best will look like this: Foreach HashMap HashSet Stream - Better not to use in this case But if you need to process big data, then the best option would be use the HashMap based method. So the top of the best look like this: HashMap HashSet Stream Foreach
With duplicate elements in array finding intersection. int [] arr1 = {1,2,2,2,2,2,2,3,6,6,6,6,6,6,}; int [] arr2 = {7,5,3,6,6,2,2,3,6,6,6,6,6,6,6,6,}; Arrays.sort(arr1); Arrays.sort(arr2); ArrayList result = new ArrayList<>(); int i =0 ; int j =0; while(i< arr1.length && j<arr2.length){ if (arr1[i]>arr2[j]){ j++; }else if (arr1[i]<arr2[j]){ i++; }else { result.add(arr1[i]); i++; j++; } } System.out.println(result);
If you don't want to use other data structures such as a Set, then the basic idea is that you want to iterate through the elements of one of the arrays and for each value see if it appears in the other. How do you see whether it appears in the other array? Walk through the elements in the other array and for each one, see if its value is equal to the value you are looking for. I suspect that you will be best served by trying to work through this problem on your own beyond this point if your goal in taking the class is to learn to write Java well, but it you get stuck you might consider updating your question with the code that you have written so you can get more detailed feedback and pointers in the right direction.
Try this: public static void main(String[] args) { int[] arr1 = new int[]{1, 2, 3, 4, 5}; int[] arr2 = new int[]{3, 2, 5, 9, 11}; getIntersection(arr1, arr2); } public static Object[] getIntersection(int[] arr1, int[] arr2) { List<Integer> list = new ArrayList<Integer>(); for (int i = 0; i < arr1.length; i++) { for (int j = 0; j < arr2.length; j++) { if (arr1[i] == arr2[j]) { list.add(arr1[i]); } } } return list.toArray(); }
You can find the intersection of two arrays with: T[] result = Arrays.stream(a1) .filter(new HashSet<>(Arrays.asList(a2))::contains) .toArray(T[]::new); where T should be substitutable by a reference type e.g. String, Integer, etc. although the above may seem like it's creating a new set for each element, it's not the case at all. instead only one set instance is created. The above code is equivalent to: List<T> list = new ArrayList<>(); HashSet<T> container = new HashSet<>(Arrays.asList(a2)); for (T s : a1) { if (container.contains(s)) list.add(s); } T[] result = list.toArray(new T[0]);
finding intersection includes duplicate using the hash map. Output: 1 2 2 15 9 7 12 public static void main(String[] args) { int[] arr1 = {1, 2, 2, 1, 5, 9, 15, 9, 7, 7, 12}; int[] arr2 = {1, 2, 2, 3, 4, 15, 9, 7, 12, 14}; printIntersect(arr1, arr2); } private static void printIntersect(int[] arr1, int[] arr2) { Map<Integer, Integer> map = new HashMap<>(); //put first array to map for (int i = 0; i < arr1.length; i++) { if (!map.containsKey(arr1[i])) { map.put(arr1[i], 1); } else { map.put(arr1[i], map.get(arr1[i]) + 1); } } //check all value in array two for (int i = 0; i < arr2.length; i++) { //if exist and value>1 then decrement value //if value is 1 remove from map if (map.containsKey(arr2[i])) { System.out.print(arr2[i] + " "); if (map.get(arr2[i]) > 1) { map.put(arr2[i], map.get(arr2[i]) - 1); } else { map.remove(arr2[i]); } } } }
if the arrays are sorted int a1[]=new int[] {1,2,3,5,7,8}; int a2[]=new int [] {1,5,6,7,8,9}; // get the length of both the array int n1=a1.length; int n2=a2.length; //create a new array to store the intersection int a3[]=new int[n1]; //run the loop and find the intersection int i=0,j=0,k=0; while(i<n1&& j<n2) { if(a1[i]<a2[j]) { // a1 element at i are smaller than a2 element at j so increment i i++; }else if(a1[i]>a2[j]) { // a2 element at i are smaller than a2 element at j so increment j j++; }else { // intersection element store the value and increment i, j, k to find the next element a3[k]=a1[i]; i++; j++; k++; } } for(int l=0;l<a3.length;l++) { System.out.println(a3[l]); }
How to Find the Intersection of 3 unsorted arrays in Java:- I have used the Core Java approach using for loops & using Arrays.copyOf to achieve this. public class Intersection { public void intersection3Arrays(int ar1[], int ar2[], int ar3[]) { Arrays. sort(ar1); Arrays. sort(ar2); Arrays. sort(ar3); int ar1Len = ar1.length; int ar2Len = ar2.length; int ar3Len = ar3.length; int larArray = ar3Len > (ar1Len > ar2Len ? ar1Len : ar2Len) ? ar3Len : ((ar1Len > ar2Len) ? ar1Len : ar2Len); System.out.println("The largest array is " +larArray); int[] inputArray1 = Arrays.copyOf(ar1, larArray); int[] inputArray2 = Arrays.copyOf(ar2, larArray); int[] inputArray3 = Arrays.copyOf(ar3, larArray); Integer[] inputArray11 = new Integer[inputArray1.length]; Integer[] inputArray22 = new Integer[inputArray2.length]; Integer[] inputArray33 = new Integer[inputArray3.length]; for (int i = 0; i < inputArray11.length; i++) { if (inputArray11[i] == null){ inputArray1[i] = 0; } } for (int i = 0; i < inputArray22.length; i++) { if (inputArray22[i] == null){ inputArray1[i] = 0; } } for (int i = 0; i < inputArray33.length; i++) { if (inputArray33[i] == null){ inputArray1[i] = 0; } } for (int i = 0; i < inputArray11.length; i++) for (int j = 0; j < inputArray22.length; j++) for (int k = 0; k < inputArray33.length; j++) if (inputArray11[i] == inputArray22[j] && inputArray11[i] == inputArray33[k]) { System.out.print(inputArray11[i]+" "); } } public static void main(String[] args) { Intersection3Arrays arrays = new Intersection3Arrays(); int ar1[] = { 1, 2, 5, 10, 20, 40, 80 }; int ar2[] = { 80, 100, 6, 2, 7, 20 }; int ar3[] = {3, 4, 15, 20, 30, 70, 80, 120}; arrays.intersection3Arrays(ar1, ar2, ar3); } }
If you ever wanted to implement this in python, this is one way that you can find intersection. #find intersection def find_intersec(list_a, list_b): return set(list_a).intersection(list_b) #since lists are kind of like arrays in python we use two lists list_a = [ 4, 9, 1, 17, 11, 26, 28, 10,28, 26, 66, 91] list_b = [9, 9, 74, 21, 45, 11, 63,10] print(find_intersec(list_a, list_b))
I hope this example will simple one.pass two arrays and you will definitely get INTERSECTION of array without duplicate items. private static int[] findInterserctorOfTwoArray(int[] array1, int[] array2) { Map<Integer,Integer> map=new HashMap<>(); for (int element : array1) { for (int element2 : array2) { if(element==element2) { map.put(element, element); } } } int[] newArray=new int[map.size()]; int con=0; for(Map.Entry<Integer, Integer> lst:map.entrySet()) { newArray[con]=lst.getValue(); con++; } return newArray; }
optimised for sorted arrays using only one loop. int a1[]=new int[] {1,2,3,5,7,8}; int a2[]=new int [] {1,5,6,7,8,9}; // sort both the array Arrays.sort(a1); Arrays.sort(a2); // get the length of both the array int n1=a1.length; int n2=a2.length; //create a new array to store the intersection int a3[]=new int[n1]; //run the loop and find the intersection int i=0,j=0,k=0; while(i<n1&& j<n2) { if(a1[i]<a2[j]) { // a1 element at i are smaller than a2 element at j so increment i i++; }else if(a1[i]>a2[j]) { // a2 element at i are smaller than a2 element at j so increment j j++; }else { // intersection element store the value and increment i, j, k to find the next element a3[k]=a1[i]; i++; j++; k++; } } for(int l=0;l<a3.length;l++) { System.out.println(a3[l]); }
Primitive Iterator: 6 Times Faster than HashSet Tested on sorted arrays of 10,000,000 random elements, values between 0 and 200,000,000. Tested on 10 processor i9 with 4GB heap space. Sort time for two arrays was 1.9 seconds. results: primitive() - 1.1 seconds public static int[] primitive(int[] a1, int[] a2) { List<Integer> list = new LinkedList<>(); OfInt it1 = Arrays.stream(a1).iterator(); OfInt it2 = Arrays.stream(a2).iterator(); int i1 = it1.next(); int i2 = it2.next(); do { if (i1==i2) { list.add(i1); i1 = it1.next(); } if (i1 < i2) i1 = it1.next(); if (i2 < i1) i2 = it2.next(); } while(it1.hasNext() && it2.hasNext()); if (i1==i2) list.add(i1); return list.stream().mapToInt(Integer::intValue).toArray(); } boxed() - 6.8 seconds public static int[] boxed(int[] a1, int[] a2) { return Arrays.stream(a1) .filter(new HashSet<>(Arrays.stream(a2).boxed() .collect(Collectors.toList()))::contains) .toArray(); }
How to find the permutation of a sort in Java
I want to sort an array and find the index of each element in the sorted order. So for instance if I run this on the array: [3,2,4] I'd get: [1,0,2] Is there an easy way to do this in Java?
Let's assume your elements are stored in an array. final int[] arr = // elements you want List<Integer> indices = new ArrayList<Integer>(arr.length); for (int i = 0; i < arr.length; i++) { indices.add(i); } Comparator<Integer> comparator = new Comparator<Integer>() { public int compare(Integer i, Integer j) { return Integer.compare(arr[i], arr[j]); } } Collections.sort(indices, comparator); Now indices contains the indices of the array, in their sorted order. You can convert that back to an int[] with a straightforward enough for loop.
import java.util.*; public class Testing{ public static void main(String[] args){ int[] arr = {3, 2, 4, 6, 5}; TreeMap map = new TreeMap(); for(int i = 0; i < arr.length; i++){ map.put(arr[i], i); } System.out.println(Arrays.toString(map.values().toArray())); } }
One way to achieve this is to make a list of pairs with the starting index as the second part of the pair. Sort the list of pairs lexicographically, then read off the starting positions from the sorted array. Starting array: [3,2,4] Add pairs with starting indexes: [(3,0), (2,1), (4,2)] Sort it lexicographically [(2,1), (3,0), (4,2)] then read off the second part of each pair [1,0,2]
import java.io.*; public class Sample { public static void main(String[] args) { int[] data = {0, 3, 2, 4, 6, 5, 10};//case:range 0 - 10 int i, rangeHigh = 10; int [] rank = new int[rangeHigh + 1]; //counting sort for(i=0; i< data.length ;++i) ++rank[data[i]]; for(i=1; i< rank.length;++i) rank[i] += rank[i-1]; for(i=0;i<data.length;++i) System.out.print((rank[data[i]]-1) + " ");//0 2 1 3 5 4 6 } }
As an update, this is relatively easy to do in Java 8 using the streams API. public static int[] sortedPermutation(final int[] items) { return IntStream.range(0, items.length) .mapToObj(value -> Integer.valueOf(value)) .sorted((i1, i2) -> Integer.compare(items[i1], items[i2])) .mapToInt(value -> value.intValue()) .toArray(); } It somewhat unfortunately requires a boxing and unboxing step for the indices, as there is no .sorted(IntComparator) method on IntStream, or even an IntComparator functional interface for that matter. To generalize to a List of Comparable objects is pretty straightforward: public static <K extends Comparable <? super K>> int[] sortedPermutation(final List<K> items) { return IntStream.range(0, items.size()) .mapToObj(value -> Integer.valueOf(value)) .sorted((i1, i2) -> items.get(i1).compareTo(items.get(i2))) .mapToInt(value -> value.intValue()) .toArray(); }