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]);
}
Related
It has been a long since something came to my mind while starting to code and using lists or array lists. When comparing values of one array to every other elements in another array, I used to do it in two for loops since it was the easiest way to do that.but recently I came to know that it increases much time complexity, I thought about another solution.can anyone help me in solving this case using any algorithm. I am using java.but solution in any language would be fine. just the algorithm to do that is needed. Thanks in advance.
This is what i am doing:
a1 = [1,2,3,4,5]
b1 = [9,5,4,3,8,3,7]
I want to check how much time an element in a1 occurs in b1
So what i am doing is:
count = 0;
for(int i = 0;i <a1.length;i++)
{
for(j=0;j<b1.length;j++)
{
if (a1[i] == b1[j])
{
count = count+1;
}
}
}
print("count is" count);
Theres no need of loop to obtain what you want
ArrayList<Integer> l1 = new ArrayList<Integer>();
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
l1.add(5);
ArrayList<Integer> l2 = new ArrayList<Integer>();
l2.add(9);
l2.add(5);
l2.add(4);
l2.add(3);
l2.add(8);
l2.add(3);
l2.add(7);
ArrayList<Integer> lFiltered = new ArrayList<Integer>(l2);
lFiltered.removeAll(l1);
int Times = l2.size() - lFiltered.size();
System.out.println("number of migrants : " + Times);
Suffice it to to generate from l2 a list without elements and l1 and to count elements which have been removed
Use hashing, e.g. using a Set or Map
If you want to compare the objects as a whole:
properly implement equals and hashcode for your class (if not implemented already)
put all the elements of list A into a Set, then see which elements from list B are in that Set
If you just want to compare objects by some attribute:
define a method that maps the objects to that attribute (or combination of attriutes, e.g. as a List)
create a Map<KeyAttributeType, List<YourClass>> and for each element from list A, add the element to that Map: map.get(getKey(x)).add(x)
for each element from list B, calculate the value of the key function and get the elements it "matches" from the map: matches = map.get(getKey(y))
Given your code, your case seems to be a bit different, though. You have lists or arrays of numbers, so no additional hashing is necessary, and you do not just want to see which items "match", but count all combinations of matching items. For this, you could create a Map<Integer, Long> to count how often each element of the first list appears, and then get the sum of those counts for the elements from the second list.
int[] a1 = {1,2,3,4,5};
int[] b1 = {9,5,4,3,8,3,7};
Map<Integer, Long> counts = IntStream.of(b1).boxed()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println(counts); // {3=2, 4=1, 5=1, 7=1, 8=1, 9=1}
long total = IntStream.of(a1).mapToLong(x -> counts.getOrDefault(x, 0L)).sum();
System.out.println(total); // 4
Of course, instead of using the Stream API you can just as well use regular loops.
Use ArrayLists.
To compare the content of both arrays:
ArrayList<String> listOne = new ArrayList<>(Arrays.asList(yourArray1);
ArrayList<String> listTwo = new ArrayList<>(Arrays.asList(yourArray);
listOne.retainAll(listTwo);
System.out.println(listOne)
To find missing elements:
listTwo.removeAll(listOne);
System.out.println(listTwo);
To enumerate the Common elements:
//Time complexity is O(n^2)
int count =0;
for (String element : listOne){
for (String element2: listTwo){
if (element.equalsIgnoreCase(elemnt2){
count += 1;
}
}
}
Is there a way i could return in an array the common elements of 2 or more arrays? I know having some of the methods under lists could do it but is there a way to do it by only using arrays? I made my own get and length btw since i am creating a an array called OrderedIntList.
Example would be:
1,3,5
1,6,7,9,3
1,3,10,11
Result: 1,3
I tried this and it outputs the common elements between two arrays and not all.
I know there's something wrong but i do not how to make it work like it suppose to work :(
//returns the common elements of inputted arrays
public static OrderedIntList common(OrderedIntList ... lists){
int[] list = new int[10];
for(int x = 1; x <= lists.length -1; x++){
for(int q = 0; q < lists[0].length()-1; q++) {
for(int z = 0; z < lists[x].length(); z++) {
if (lists[0].get(q)==lists[x].get(z)){
list[q] = lists[0].get(q);
}
}
}
}
OrderedIntList newlist = new OrderedIntList(list);
return newlist;
}
This can be an easy algorithm to solve it...
1) Instantiate an instance variable of type array called
"commonElements" pointing to the elements of the first Array. At the
beginning these are your common elements.
2) Create a method call getCommonElements(int[] commonElements,
int[] newList). This method manipulates the commonElements array to leave
it with only the common elements between the two. (p.s Use a temporary
array to achieve this if you find it easier)
3) Iterate over all the arrays present in "lists" starting from the
second array.
4) call the method at point 2 for each array .
All the difficult part for you it's to implement a method that given 2 arrays finds the common elements!
You can use
org.apache.commons.collections.CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)
to get the intersection of two lists (elements presents in both lists)
And to pass your array as a Collection: java.util.Arrays.asList(Object[] a);
But working on arrays is tedious, at best. You should consider why you don't want to use a Collection...
As a partial answer, you're probably doing too much work by fully reimplementing an OrderedIntList the way you're doing, since ArrayList and friends already come with sorting baked in via the Collections class.
import java.util.Collections;
public class OrderedIntList extends ArrayList<Integer> {
#override // to effect sorted inserts
public void add(Integer i) {
this.add(i);
Collections.sort(this);
// done.
}
}
Wanting to do this for pure arrays is a nice exercise, but then you'll be better of implementing sorting properly with a quick sort (you can't websearch for a java implementation of that without getting a million results) or an insert sort (equally websearchable), and follow the same recipe.
any time you push a number into the array:
guess where the number goes (although that's optional),
insert the number,
resort your array if you know your guess wasn't perfect.
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).
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.
I have 2 arrays of data in Java. Based on the order of first array I have to sort the next array.
E.g -
String[] Array1 = {"EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA"};
String[] Array2 = {"MIDDLEEAST","EUROPE","AUSTRALIA","OTHERs","ASIA","EUROPE"};
My output should look like:
{"EUROPE","EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA","ASIA"}
What is the best way to do it?
To sort you need to define a sorting order so given element A and B, you can determine easily if A should go before or after B in the sorted list.
This concept is formalized with the concept of a Comparator in Java.
In this case the sorting order is defined by the order of the elements in a list. The simplest approach is given A and B to find each of them in the original list, note the index found, and compare the indexes to find out which one goes first.
Depending on the size of your data this might be too slow. You can then create a HashMap<String,Long> which holds the index of a given string in Array1. Here it would hold "DEF"->0, "ABC"->1, "XYZ"->2.
May be this:
1) Sort both of them.
2) Create blank result table
3) Take first elem from sorted Array2 and put it to result table with the original index of the first elem on sorted Array1
3) Repeat the step 3 on the second element and so on.
The computational complexity would be like sorting method used: O(nlogn) for quicksort
You can definitely do this in O(n log n). But the best approach depends on what is more important: quick, clean code or not allocating extra memory.
If you don't care about using extra memory, you can allocate a separate array, where each element is a pair:
public class Pair implements Comparable {
...
}
Then you would sort the array of pairs using Arrays.sort(Object[]).
If you don't want to allocate quite so much space, you can use an auxiliary array that contains the indexes in Integer form:
final String[] array1 = ...;
final String[] array2 = ...;
assert array1.length == array2.length;
Comparator<Integer> c = new Comparator<Integer> {
int compare(Integer a, Integer b) {
return array1[a].compareTo(array1[b]);
}
};
Integer[] aux = new Integer[array1.length];
for (int i = 0; i < aux.length; ++i) { aux[i] = i; }
Arrays.sort(aux, c);
String[] result = new String[array1.length];
for (int i = 0; i < aux.length; ++i) {
result[i] = array2[aux[i]];
}
If you are trying to do the entire thing in-place and not allocate additional memory, then you will need to implement one of the n-log-n sort algorithms yourself...
There are (at least) two ways to sort one array and reorder a second array so corresponding elements still match. Both require constructing a third array and writing a custom comparison function.
Method 1
Define a custom object that contains one element of each array. (In your case, it might be a two-element String array.) Write a comparator (or implement Comparable) for the custom object that simply compares the elements from the first array. Build an array of the custom objects from the two input arrays, sort the third array, and then extract the results.
This is the method most commonly recommended for this problem.
Method 2
Construct an array of Integer indexes initialized to 0, 1, 2, ..., n-1 (where n == Array1.length). Sort the index array using a comparator that compares indexes by comparing the Array1 elements that they index.
The second method will be faster and will not require as much object construction.
Two other ideas:
Could these values be an enum rather than a set of strings? The natural order of an enum is the order of declaration, so Arrays.sort() would just work.
Helper code exists in Guava's Ordering.explicitOrder(List):
String[] explicitOrder = {"EUROPE", "MIDDLEEAST", "OTHERs", "AUSTRALIA"};
String[] toSort = ...
Comparator<String> comparator = Ordering.explicit(Arrays.asList(explicitOrder));
String[] sorted = Arrays.sort(toSort, comparator);