Inversed array but not a hashmap - java

In Java, I have an unsorted int[] values = new int[100]; array. All the values are unique (different) and they are uncomparable (no way to sort). Can I construct a kind of inversed function which will give me an index of a certain value in the array if I specify that value?
Currently done it using a hashmap:
IntIntMap indices = new IntIntOpenHashMap(100, 1);
for (int i = 0; i < 100; i++) {
indices.put(values[i], i);
}
Any other solution? Would prefer a faster one.

Yes, you could create your own hash function or research a specific one for your case. It depends on the structure of the values and whether this is truly a bottleneck in the program.

Related

Create empty array without using List<object>

If I want to create an "unlimited" array I know I can use a list (There is a lot of information on this and other forums)
But what if I don't want to make a list? Is there another way?
Because I want to use a float array in another function and it's kind of a hassle to use a list in this case.
This is what I wrote so far with the listing
List<Float> listfloat = new ArrayList();
listfloat.add((float)0.1); //example
listfloat.add((float)1.2);
float data[]= new float[listfloat.size()];
for(int i = 0; i < listfloat.size(); ++i)
{
data[i] = listfloat.get(i);
}
return data ;
But I would prefer something like this
float data[]; //unknown size
for(i=0 ; i< sizeiwant; i++)
{
data[i] = mydata;
}
return data ;
I know that it will work! I just want to optimise my coding =)
Thank you for reading =)
There are 2 ways you can do this:
You could convert a list to an Array using list.ToArray()
You could dynamically resize the array by changing the size of the array every time you add an element to the array. Here is how you would do that:
//initialize array of size 10.
int[] array=new int[10];
//make copy of array
int[] arrayCopy=array.clone();
//expand array size by 1
array=new int[array.length+1];
//give value to new array index
array[array.length-1]=0;
//copy values from 'arrayCopy' to array
for(int x=0;x<arrayCopy.length;x++){
array[x]=arrayCopy[x];
}
Hope this helped.
With the information you provided I would recommend to use an Array and create a method that is called when your array is full and returns a copy of the original array with more space in this way is you are kind of simulating dynamic size allocation.
Arrays in java are fixed-size, so your second piece of code is never going to work.
If you want a data type that can resize, you should use an ArrayList. On the other hand, there are times when using primitive array like a float[] is quicker and more convenient.
As a result, the need to convert between List<Float> and float[] in the way you do it in the first block of code is fairly common, and there is no way to do it in one line (unless you use an external library).
I advise writing a utility method to do the conversion
public static float[] listToArray(List<Float> list) {
int size = list.size();
float[] temp = new float[size];
for (int i = 0; i < size; i++)
temp[i] = list.get(i);
return temp;
}
(This method could be improved, as it has poor performance for a LinkedList where get is linear).
Annoyingly, you need 8 methods like this for the 8 primitive types, and 8 methods to do the conversions in the other direction. As things stand at the moment, there is no way to write generic code over primitive types, so code duplication like this is common.

How to keep the N highest values?

I'm doing a method that takes the value from a lot of objects with double getDelay(). But I need some help because I don't know how to save the 6 higher values. I thought to make a loop and save values in an array but I don't know how to insert a new value and delete the smallest and reordering the array. Any suggestions to save and order the values?
EDIT:
Thanks to all, I forgot to say that I have to save the object (or the name in a String with getName(), I don't care) too. I thought use queues but I don't control them a lot. How can I order it? Because if I use Array.sort I don't know of what objects are this values
You can just use Arrays.sort(yourArr) and then take the last N entries.
See answer: Java - Ordering array values from highest to lowest
You can add all values in an double[] array. Then use Arrays.sort() like this:
Arrays.sort(array,Collections.reverseOrder()); // this will sort array in descending order
Now you can access first 6 elements of this array to get largest 6 values.
EDIT: If you want to keep objects as well, you can use TreeMap<Double,Object>. Populate it with ids and objects. The elements in TreeMap are sorted by key which is Double here.
You can then retreive last 6 elements in TreeMap like this:
List<Object> highest = new ArrayList<Object>;
for(int i=0; i<6; i++){
Double last = treemap.getLastKey();
Object objLast = treemap.get(last);
hightest.put(objLast);
treemap.remove(last);
}
Note: I have used ArrayList to store objects with highest double if you want to keep both you can instead use Map implementation to save both double and Object. Hope this helps.
You'll actually want to create a Comparator<MyObject> and sort an array of MyObject directly:
Comparator<MyObject> myComparator = (o1, o2) -> {
o1.getDelay() > o2.getDelay() ? -1 : (o1.getDelay() < o2.getDelay() ? 1 : 0);
} // Reverse order by getDelay()
MyObject[] stuff;
Arrays.sort(stuff, myComparator);
for (int i = 0; i < 6; i++) {
doSomething(stuff[i]);
}

declaring multiple java arrays in a loop

Hi guys thanks for helping in advance this is not the real code it is just the idea i want to reach
for (int i = 1, i< some number ; i ++ )
float [][] sts + i = new float[9][9];
The idea is to have 2 dimensional arrays with dynamic names initializing in a loop
sts1
sts2
sts3
.
.
.
.
.
For your problem, where naming is sequential based on the value of i, an ArrayList could do the job as you can iterate over it.
However, a more general approach that enables you accessing your arrays by some String name (even if this was random and not sequential as in your case) would be to use a Map<String, float[][]>, where the key String of the Map is the name you have given to your array.
Map<String, float[][]> myMap = new HashMap<String, float[][]>();
for(int i = 0; i < someNumber; ++i)
{
myMap.put("sts" + i, new float[9][9]);
}
then access each array by myMap.get(_aName_);
If you create every 2 dimensional array in the loop, then the variabl (like sts1) will only be local to the loop. So after the loop the variable is out of scope (but I think you want to use them after the loop, that's why you want different names). So to use the created variables, you have to use an array. And if you use an array, the question of naming ceases.
ArrayList<float[][]> l = new ArrayList<float[][]>();
for(int i = 0; i < someNumber; ++i)
{
l.add(new float[9][9]);
}
You can't create variable names dynamically in Java. Just do this
float[][][] sts = new float[someNumber][9][9];
Then you can use sts[0], sts[1] where you wanted to use sts1, sts2 etc.

Getting the indices of an unsorted double array after sorting

This question comes as a companion of this one that regarded fastest sorting of a double array.
Now I want to get the top-k indices corresponding to the unsorted array.
I have implemented this version which (unfortunately) uses autoboxing and HashMap as proposed in some answers including this one:
HashMap<Double, Integer> map = new HashMap<Double, Integer>();
for(int i = 0; i < numClusters; i++) {
map.put(scores[i], i);
}
Arrays.sort(scores);
HashSet<Integer> topPossibleClusters = new HashSet<Integer>();
for(int i = 0; i < numClusters; i++) {
topPossibleClusters.add(map.get(scores[numClusters - (i+1)]));
}
As you can see this uses a HashMap with keys the Double values of the original array and as values the indices of the original array.
So, after sorting the original array I just retrieve it from the map.
I also use HashSet as I am interested in deciding if an int is included in this set, using .contains() method. (I don't know if this makes a difference since as I mentioned in the other question my arrays are small -50 elements-). If this does not make a difference point it out though.
I am not interested in the value per se, only the indices.
My question is whether there is a faster approach to go with it?
This sort of interlinking/interlocking collections lends itself to fragile, easily broken, hard to debug, unmaintainable code.
Instead create an object:
class Data {
double value;
int originalIndex;
}
Create an array of Data objects storing the original value and index.
Sort them using a custom comparator that looks at data.value and sorts descending.
Now the top X items in your array are the ones you want and you can just look at the value and originalIndex as you need them.
As Tim points out linking a multiple collections is rather errorprone. I would suggest using a TreeMap as this would allow for a standalone solution.
Lets say you have double[] data, first copy it to a TreeMap:
final TreeMap<Double, Integer> dataWithIndex = new TreeMap<>();
for(int i = 0; i < data.length; ++i) {
dataWithIndex.put(data[i], i);
}
N.B. You can declare dataWithIndex as a NavigableMap to be less specific, but it's so much longer and it doesn't really add much as there is only one implementation in the JDK.
This will populate the Map in O(n lg n) time as each put is O(lg n) - this is the same complexity as sorting. In reality it will be probably be a little slower, but it will scale in the same way.
Now, say you need the first k elements, you need to first find the kth element - this is O(k):
final Iterator<Double> keyIter = dataWithIndex.keySet().iterator();
double kthKey;
for (int i = 0; i < k; ++i) {
kthKey = keyIter.next();
}
Now you just need to get the sub-map that has all the entries upto the kth entry:
final Map<Double, Integer> topK = dataWithIndex.headMap(kthKey, true);
If you only need to do this once, then with Java 8 you can do something like this:
List<Entry<Double, Integer>> topK = IntStream.range(0, data.length).
mapToObj(i -> new SimpleEntry<>(data[i], i)).
sorted(comparing(Entry::getKey)).
limit(k).
collect(toList());
i.e. take an IntStream for the indices of data and mapToObj to an Entry of the data[i] => i (using the AbsractMap.SimpleEntry implementation). Now sort that using Entry::getKey and limit the size of the Stream to k entries. Now simply collect the result to a List. This has the advantage of not clobbering duplicate entries in the data array.
It is almost exactly what Tim suggests in his answer, but using an existing JDK class.
This method is also O(n lg n). The catch is that if the TreeMap approach is reused then it's O(n lg n) to build the Map but only O(k) to reuse it. If you want to use the Java 8 solution with reuse then you can do:
List<Entry<Double, Integer>> sorted = IntStream.range(0, data.length).
mapToObj(i -> new SimpleEntry<>(data[i], i)).
sorted(comparing(Entry::getKey)).
collect(toList());
i.e. don't limit the size to k elements. Now, to get the first k elements you just need to do:
List<Entry<Double, Integer>> subList = sorted.subList(0, k);
The magic of this is that it's O(1).

How to remove element from an array

I have an array for example:
String [][] test = {{"a","1"},
{"b","1"},
{"c","1"}};
Can anyone tell me how to remove an element from the array. For example I want to remove item "b", so that the array looks like:
{{"a","1"},
{"c","1"}}
I can't find a way of doing it. What I have found here so far is not working for me :(
You cannot remove an element from an array. The size of a Java array is determined when the array is allocated, and cannot be changed. The best you can do is:
Assign null to the array at the relevant position; e.g.
test[1] = null;
This leaves you with the problem of dealing with the "holes" in the array where the null values are. (In some cases this is not a problem ... but in most cases it is.)
Create a new array with the element removed; e.g.
String[][] tmp = new String[test.length - 1][];
int j = 0;
for (int i = 0; i < test.length; i++) {
if (i != indexOfItemToRemove) {
tmp[j++] = test[i];
}
}
test = tmp;
The Apache Commons ArrayUtils class has some static methods that will do this more neatly (e.g. Object[] ArrayUtils.remove(Object[], int), but the fact remains that this approach creates a new array object.
A better approach would be to use a suitable Collection type. For instance, the ArrayList type has a method that allows you to remove the element at a given position.
There is no built-in way to "remove" items from a regular Java array.
What you want to use is an ArrayList.
You could set the entry in the array to null (test[0][1] = null;). However, "removing" the item such that the array will have one element less than before is not doable without recreating the array. If you plan to change data in the data structure regularly an ArrayList (or another Collection class depending on your needs) might be more convenient.
My solution is:
You cannot remove an element from an array => it's correct, but we can do something to change current array.
No need assign null to the array at the relevant position; e.g.
test[1] = null;
Create a new array with the element removed; e.g.
String[][] temp = new String[test.length - 1][];
Need to get index at string/array to remove: IndexToRemove
for (int i = 0; i < test.length-1; i++) {
if (i<IndexToRemove){
temp[i]=test[i];
}else if (i==IndexToRemove){
temp[i]=test[i+1];
}else {
temp[i]=test[i+1];
}
}
test = temp;
Hope it helpful!

Categories