For a problem I'm designing in Java, I'm given a list of dates and winning lottery numbers. I'm supposed to do things with them, and spit them back out in order. I decided to choose a LinkedHashMap to solve it, the Date containing the date, and int[] containing the array of winning numbers.
Thing is, when I run the .values() function, I'm noticing the numbers are no longer ordered (by insertion). The code I'm running is:
for(int i = 0; i < 30; i++){ //testing first 30 to see if ordered
System.out.println(Arrays.toString((int [])(winningNumbers.values().toArray()[i])));
}
Can anyone see what exactly I'm doing wrong? Tempted almost to just use .get() and iterate through the dates, since the dates do go in some order, but that might make using a LinkedHashMap moot. Might as well be using a 2-D ArrayList[][] in that case. Thanks in advance!
EDIT: Adding code for further examination!
Lottery Class: http://pastebin.com/9ezF5U7e
Text file: http://pastebin.com/iD8jm7f8
To test, call checkOldLTNums(). Just pass it any int[] array, it doesn't utilize it, at least relevant to this problem. The output is different from the first lines in the .txt, which is organized. Thanks!
EDIT2:
I think I figured out why it fails. I used a smaller .txt file, and the code worked perfectly. It might be that it isn't wise to load 1900 entries of stuff into memory. I suppose it's better to just load individual lines and compare them instead of grabbing everything at once. Is this logic sound? Any advice going from here would be useful.
The values() method will return the Map's values in the same order they were inserted, that's what ordered means, don't confuse it with sorted, that means a different thing - that the items follow the ordering defined by the value's Comparator or its natural ordering if no comparator was provided.
Perhaps you'd be better off using a SortedMap that keeps the items sorted by key. To summarise: LinkedHashMap is ordered and TreeMap is sorted.
Try using a TreeMap instead. You should get the values in ascending key order that way.
I can't believe I missed this. I did some more troubleshooting, and realized some of the Date keys were replacing others. After doing some testing, I finally realized that the formatting I was using was off: "dd/MM/yyyy" instead of "MM/dd/yyyy". That's what I get for copy-pasting, haha. Thanks to all who helped!
Related
In Java, I have an ArrayList with a list of objects. Each object has a date field that is just a long data type. The ArrayList is sorted by the date field. I want to insert a new object into the ArrayList so that it appears in the correct position with regard to its date. The only solution I can see is to iterate through all the items and compare the date field of the object being inserted to the objects being iterated on and then insert it once I reach the correct position. This will be a performance issue if I have to insert a lot of records.
What are some possible ways to improve this performance? Maybe an ArrayList is not the best solution?
I would say that you are correct in making the statement:
Maybe an ArrayList is not the best solution
Personally, I think that a tree structure would be better suited for this. Specifically Binary Search Tree, which is sorted on the object's date time. Once you have the tree created, you can use binary search which would take O(log n) time.
Whether or not binary search + O(n) insertion is bad for you depends on at least these things:
size of the list,
access pattern (mostly insert or mostly read),
space considerations (ArrayList is far more compact than the alternatives).
Given the existence of these factors and their quite complex interactions you should not switch over to a binary search tree-based solution until you find out how bad your current design is—through measurements. The switch might even make things worse for you.
I would consider using TreeSet and make your item Comparable. Then you get everything out of the box.
If this is not possible I would search for the index via Collections.binarySearch(...).
EDIT: Make sure performance is an issue before you start optimizing
first you should sort ArrayList Using:
ArrayList<Integer> arr = new ArrayList<>();
...
Collections.sort(arr);
Then Your Answer is:
int index = Collections.binarySearch(arr , 5);
I've come across an interesting problem which I would love to get some input on.
I have a program that generates a set of numbers (based on some predefined conditions). Each set contains up to 6 numbers that do not have to be unique with integers that ranges from 1 to 100).
I would like to somehow store every set that is created so that I can quickly check if a certain set with the exact same numbers (order doesn't matter) has previously been generated.
Speed is a priority in this case as there might be up to 100k sets stored before the program stops (maybe more, but most the time probably less)! Would anyone have any recommendations as to what data structures I should use and how I should approach this problem?
What I have currently is this:
Sort each set before storing it into a HashSet of Strings. The string is simply each number in the sorted set with some separator.
For example, the set {4, 23, 67, 67, 71} would get encoded as the string "4-23-67-67-71" and stored into the HashSet. Then for every new set generated, sort it, encode it and check if it exists in the HashSet.
Thanks!
if you break it into pieces it seems to me that
creating a set (generate 6 numbers, sort, stringify) runs in O(1)
checking if this string exists in the hashset is O(1)
inserting into the hashset is O(1)
you do this n times, which gives you O(n).
this is already optimal as you have to touch every element once anyways :)
you might run into problems depending on the range of your random numbers.
e.g. assume you generate only numbers between one and one, then there's obviously only one possible outcome ("1-1-1-1-1-1") and you'll have only collisions from there on. however, as long as the number of possible sequences is much larger than the number of elements you generate i don't see a problem.
one tip: if you know the number of generated elements beforehand it would be wise to initialize the hashset with the correct number of elements (i.e. new HashSet<String>( 100000 ) );
p.s. now with other answers popping up i'd like to note that while there may be room for improvement on a microscopic level (i.e. using language specific tricks), your overal approach can't be improved.
Create a class SetOfIntegers
Implement a hashCode() method that will generate reasonably unique hash values
Use HashMap to store your elements like put(hashValue,instance)
Use containsKey(hashValue) to check if the same hashValue already present
This way you will avoid sorting and conversion/formatting of your sets.
Just use a java.util.BitSet for each set, adding integers to the set with the set(int bitIndex) method, you don't have to sort anything, and check a HashMap for already existing BitSet before adding a new BitSet to it, it will be really very fast. Don't use sorting of value and toString for that purpose ever if speed is important.
I have the need to take an ArrayList<Conference> conferences, where Conference contains a public Date beginDate parameter, and sort as follows: first, separate conferences into buckets which represent unique months for beginDate, and then sort on beginDate itself within the buckets. I'm sure this is a common need so I was hoping someone here would have some tips.
My idea for this follows. Please tell me why it is sub-optimal :)
Create a HashMap<Date, ArrayList<Conference>>.
Iterate over conferences and use a special static function to find the first day of the month of their beginDate, check if there is an ArrayList<Conference> for that Date. then add them to the ArrayList for that Date (which should all be the same because first_day_of_month(any_day_in_month) is the same.
Iterate over each ArrayList member of the HashMap and use a standard sorting procedure to sort the ArrayList by date.
This seems more complicated than necessary, but please let me know why it's bad and what can be done to fix it.
Edit: Also, if it matters, I will eventually need to add all of those ArrayList back into an ArrayAdapter which will go in commonsware's MergeAdapter... :(
If you sort by the date from the very beginning the month's entries will be subsequent either way. After the initial sorting you can iterate over all entries and make artificial "split" if an entry is the first one of new month. I am not even sure you will need to do such differentiation (maybe becasue the question is a bit vague on this).
The total complexity of the proposed algorithm is O(nlog n), where n is the number of elements, and of course there is no better solution.
NOTE Btw this algorithm is better than the one proposed by you in operations complexity.
I got requirements-
1. Have random values in a List/Array and I need to find 3 max values .
2. I have a pool of values and each time this pool is getting updated may be in every 5 seconds, Now every time after the update , I need to find the 3 max Values from the list pool.
I thought of using Math.max thrice on the list but I dont think it as
a very optimized approach.
> Won't any sorting mechanism be costly as I am bothered about only top
3 Max Values , why to sort all these
Please suggest the best way to do it in JAVA
Sort the list, get the 3 max values. If you don't want the expense of the sort, iterate and maintain the n largest values.
Maintain the pool is a sorted collection.
Update: FYI Guava has an Ordering class with a greatestOf method to get the n max elements in a collection. You might want to check out the implementation.
Ordering.greatestOf
Traverse the list once, keeping an ordered array of three largest elements seen so far. This is trivial to update whenever you see a new element, and instantly gives you the answer you're looking for.
A priority queue should be the data structure you need in this case.
First, it would be wise to never say again, "I dont think it as a very optimized approach." You will not know which part of your code is slowing you down until you put a profiler on it.
Second, the easiest way to do what you're trying to do -- and what will be most clear to someone later if they are trying to see what your code does -- is to use Collections.sort() and pick off the last three elements. Then anyone who sees the code will know, "oh, this code takes the three largest elements." There is so much value in clear code that it will likely outweigh any optimization that you might have done. It will also keep you from writing bugs, like giving a natural meaning to what happens when someone puts the same number into the list twice, or giving a useful error message when there are only two elements in the list.
Third, if you really get data which is so large that O(n log n) operations is too slow, you should rewrite the data structure which holds the data in the first place -- java.util.NavigableSet for example offers a .descendingIterator() method which you can probe for its first three elements, those would be the three maximum numbers. If you really want, a Heap data structure can be used, and you can pull off the top 3 elements with something like one comparison, at the cost of making adding an O(log n) procedure.
I have a variable number of ArrayList's that I need to find the intersection of. A realistic cap on the number of sets of strings is probably around 35 but could be more. I don't want any code, just ideas on what could be efficient. I have an implementation that I'm about to start coding but want to hear some other ideas.
Currently, just thinking about my solution, it looks like I should have an asymptotic run-time of Θ(n2).
Thanks for any help!
tshred
Edit: To clarify, I really just want to know is there a faster way to do it. Faster than Θ(n2).
Set.retainAll() is how you find the intersection of two sets. If you use HashSet, then converting your ArrayLists to Sets and using retainAll() in a loop over all of them is actually O(n).
The accepted answer is just fine; as an update : since Java 8 there is a slightly more efficient way to find the intersection of two Sets.
Set<String> intersection = set1.stream()
.filter(set2::contains)
.collect(Collectors.toSet());
The reason it is slightly more efficient is because the original approach had to add elements of set1 it then had to remove again if they weren't in set2. This approach only adds to the result set what needs to be in there.
Strictly speaking you could do this pre Java 8 as well, but without Streams the code would have been quite a bit more laborious.
If both sets differ considerably in size, you would prefer streaming over the smaller one.
There is also the static method Sets.intersection(set1, set2) in Google Guava that returns an unmodifiable view of the intersection of two sets.
One more idea - if your arrays/sets are different sizes, it makes sense to begin with the smallest.
The best option would be to use HashSet to store the contents of these lists instead of ArrayList. If you can do that, you can create a temporary HashSet to which you add the elements to be intersected (use the putAll(..) method). Do tempSet.retainAll(storedSet) and tempSet will contain the intersection.
Sort them (n lg n) and then do binary searches (lg n).
You can use single HashSet. It's add() method returns false when the object is alredy in set. adding objects from the lists and marking counts of false return values will give you union in the set + data for histogram (and the objects that have count+1 equal to list count are your intersection). If you throw the counts to TreeSet, you can detect empty intersection early.
In case that is required the state if 2 set has intersection, I use the next snippet on Java 8+ versions code:
set1.stream().anyMatch(set2::contains)