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);
Related
This is basically to avoid redundant code. I have two different arrays, one of Float type and one Integer type. I need to find index of maximum element in both the arrays which is easy to do as I can write two different methods, one for comparing float and one for comparing Integers.
What am trying to do improve is to write just one common method which can take in either of the array as argument and can return me the max index. What I have tried unsuccessfully so far is:
private static int findMaxIndex(Object [] arr){
int maxIndex =(int) IntStream.range(0,arr.length)
.boxed()
.max(Comparator.comparingInt(i -> arr[i])) // getting compiler error here
.map(max->arr[max])
.orElse(-1);
return maxIndex;
}
and am looking to call this method like this:
Float [] a = {0.3f, 0.5f, 0.9f, 0.7f, 0.1f};
Integer []b = {3000, 250, 100, 2000, 2000, 10246};
int maxIndexFloatArray = findMaxIndex(a);
int maxIndexIntegerArray = findMaxIndex(b);
Am pretty sure there are easier ways to do this, but am a bit rusty now in hands on java code. Hope this explains the question correctly.
lambda with reduce comparing Comparables
private static <T extends Comparable<? super T>> int findMaxIndex(T[] arr) {
return IntStream.range(0, arr.length)
.reduce((l, r) -> arr[l].compareTo(arr[r]) < 0 ? r : l).orElse(-1);
}
for multiple max values the index of the first is returned
if You need the index of the last max value change the < to <=
arr can be empty but may not contain null values
You could do it old fashioned:
private <T> int findMaxIndex(T[] arr, Comparator<T> comparator){
int maxIndex= 0;
T currMax = arr[0];
for (int i=1;i<arr.length;i++){
if (comparator.compare(currMax,arr[i])<0){
currMax = arr[i];
maxIndex = i;
}
}
return maxIndex;
}
And then call it like:
private int getMaxFloatIndex(Float[] floatArr){
return findMaxIndex(floatArr,Float::compareTo);
}
Grabbing the inheritance hierarchy "from top", I would propose Comparable<X> as the input type for findMaxIndex. It is the most general type of object, of which you can distinguish a "max element":
private static <X extends Comparable<X>> int findMaxIndex(final X[] arr) {
return IntStream.range(0, arr.length)
.boxed()
.max(
(Integer idx1, Integer idx2) -> arr[idx1].compareTo(arr[idx2])
)
.orElse(-1);
}
For simplicity: Hoping/assuming arr is nor null nor contains null elements! ;) (otherwise: NPE!)
...to use it like:
Float[] a = { 0.3f, 0.5f, 0.9f, 0.7f, 0.1f };
Integer[] b = { 3000, 250, 100, 2000, 2000, 10246 };
System.out.println(findMaxIndex(a));
System.out.println(findMaxIndex(b));
Prints:
2
5
This one should do the trick:
private static <T extends Number & Comparable<T>> int findMaxIndex(T[] array) {
if (array == null || array.length == 0) return -1;
int largest = 0;
for (int i = 1; i < array.length; i++) {
if (array[i].compareTo(array[largest]) > 0) largest = i;
}
return largest;
}
You literally tell the compiler that your generic parameter T should be both a Number and Comparable to the same type.
<T extends Number & Comparable<T>> int findMaxIndex(T[] arr)
This can find the index of the maximal value based on Number, the interface of all numeric types, wrapper classes and atomic wrappers.
Also a findMax might so be made. Without the numeric aspect, just Comparable suffices, say for a String[].
I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}
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. }));
}
}
How Can I have index of a sorted array in Java?
For instance:
int[] myIntArray = new int[]{20,100,69,4};
and Arrays.sort(myIntArray) result is:
{4,20,69,100}
What if , index of original array is desired?
which means :
{3,0,2,1}
If I understood your problem correctly.
Considering there is no duplicates in you array. After you sort the array.
OPTION 1:
Writing a small helper method.
Passing each value to the below method and getting it's index.
public int findIndex(int[] iarray, int value) {
for(int i=0; i<iarray.length; i++)
if(iarray[i] == value)
return i;
}
OPTION 2:
Use org.apache.commons.lang Class ArrayUtils
public static int indexOf(int[] array,
int valueToFind)
Then,
If you are wanting to store these index in an array, take an array with initial array length and fill that array with returned index.
Declare a class that contains the index and the value, and sets up a comparator that compares just the values.
class IndexAndValue implements Comparable<IndexAndValue> {
public int index;
public int value;
public IndexAndValue(int index, int value) {
this.index = index;
this.value = value;
}
#Override
public int compareTo(IndexAndValue other) {
return Integer.compareTo(value, other.value);
}
}
Build an array of IndexAndValue of objects that contain the index and value.
IndexAndValue[] myIVArray = new IndexAndValue[myIntArray.length];
for (int i = 0; i < myIntArray.length, i++)
myIVArray[i] = new IndexAndValue(i, myIntArray[i]);
Now when you call sort on myIVArray, it will use the comparator to sort, which means it will compare the values. But the resulting array contains the IndexAndValue objects, which will keep the indexes together with the values.
(P.S. not tested, so it's possible I botched some syntax...)
(PPS. Public data members are usually evil, but I think it's OK for a small class like this whose purpose is just to hold a few values together. But if you don't like it, make them private and use accessor methods.)
I think a way to do this would be to create a class "intWithIndex" implementing Comparable. In that ways you could jeep track of the index.
public class IntWithIndex implements Comparable<IntWithIndex>{
public int value;
public int index;
#Override
Public int compareTo(intWithIndex x) {
return value - x.value;
}
}
public Test {
IntWithIndex[] myArray = ...
myArray[].sort;
}
IntWithIndex[].sort should then work, and you can check the initial indices with the index field.
Do you see what I mean ?
Additional to #SURESH ATTA, you can use Map to define your data structure, the key would be save as index and value would be your integers.
To get indexArray of sorted value without using any lib. Also take care of duplicate/multiple array element.
import java.util.Arrays;
public class IndexCal {
public static void main(String args[]) {
int[] myIntArray = new int[] { 20, 100, 69, 4, 20, 4, 100 };
int[] copyArray = new int[myIntArray.length];
System.arraycopy(myIntArray, 0, copyArray, 0, myIntArray.length);
Arrays.sort(myIntArray);
int[] indexArray = new int[myIntArray.length];
Arrays.fill(indexArray, -1);
for (int i = 0; i < copyArray.length; i++) {
int skiplength = 0;
int index = find(copyArray, myIntArray[i], 0);
while(find(indexArray, index, 0) != -1){
index = find(copyArray, myIntArray[i], skiplength++);
}
indexArray[i] = index;
}
for (int i = 0; i < copyArray.length; i++) {
System.out.println(indexArray[i]);
}
}
public static int find(int[] array, int value, int skiplength) {
for (int i = 0; i < array.length; i++)
if (array[i] == value)
if(skiplength == 0)
return i;
else
skiplength--;
return -1;
}
}
public class MaxHeap<T extends Comparable<T>> implements Heap<T>{
private T[] heap;
private int lastIndex;
public void main(String[] args){
int i;
T[] arr = {1,3,4,5,2}; //ERROR HERE *******
foo
}
public T[] Heapsort(T[]anArray, int n){
// build initial heap
T[]sortedArray = anArray;
for (int i = n-1; i< 0; i--){
//assert: the tree rooted at index is a semiheap
heapRebuild(anArray, i, n);
//assert: the tree rooted at index is a heap
}
//sort the heap array
int last = n-1;
//invariant: Array[0..last] is a heap,
//Array[last+1..n-1] is sorted
for (int j=1; j<n-1;j++) {
sortedArray[0]=sortedArray[last];
last--;
heapRebuild(anArray, 0, last);
}
return sortedArray;
}
protected void heapRebuild(T[ ] items, int root, int size){
foo
}
}
The error is on the line with "T[arr] = {1,3,4,5,2}"
Eclipse complains that there is a:
"Type mismatch: cannot convert from
int to T"
I've tried to casting nearly everywhere but to no avail.A simple way out would be to not use generics but instead just ints but that's sadly not an option. I've got to find a way to resolve the array of ints {1,3,4,5,2} into an array of T so that the rest of my code will work smoothly.
When you use a generic type, you must resolve all the type parameters, i.e. tell the compiler which concrete types you want to use instead of the placeholder T in your code. As the others already pointed out, a primitive type like int can't be used as a generic type parameter - it must be a reference type, like Integer. So you can rewrite your main method into something like
public static void main(String[] args){
int i = 5;
Integer[] arr = {1,3,4,5,2};
MaxHeap<Integer> maxHeap = new MaxHeap<Integer>();
maxHeap.heapSort(arr, i);
}
Note that it should be static. When you instantiate your class, you have to specify the type parameter Integer as above. Then you can pass it the array to be sorted.
A further note: this loop
for (int i = n-1; i< 0; i--){
...
}
will never execute - the loop condition should be i > 0 instead.
Declare arr as an Integer[] instead of a T[]. There are also a couple of other small errors that I fixed here:
public static void main(String[] args){
int i;
Integer[] arr = {1,3,4,5,2}; //ERROR HERE *******
}
public <T> T[] Heapsort(T[]anArray, int n){
// build initial heap
T[]sortedArray = anArray;
for (int i = n-1; i< 0; i--){
//assert: the tree rooted at index is a semiheap
heapRebuild(anArray, i, n);
//assert: the tree rooted at index is a heap
}
//sort the heap array
int last = n-1;
//invariant: Array[0..last] is a heap,
//Array[last+1..n-1] is sorted
for (int j=1; j<n-1;j++) {
sortedArray[0]=sortedArray[last];
last--;
heapRebuild(anArray, 0, last);
}
return sortedArray;
}
protected void heapRebuild(T[ ] items, int root, int size){
//foo
}
You've already said that T extends Comparable<T>. "int" does not extend Comparable<T> not matter how you cast it.
Erm, ever thought about what would happen if you ran this code in a MaxHeap of, say, String objects?
T does not exist until you actually instantiate the generic class. So, it does not make sense to create an array of T with integers if you don't know what T is.
EDIT: Also, generics in Java only work with reference types, and int is a value type. Try using Integer (int's wrapper class) instead.