Array out of order after sort in Java - java

I have a Java String array containing the values 1-10. When I run Arrays.sort() on it however, it becomes 1, 10, 2, 3, 4...9. Does anyone know why the 10 is out of order? Is it because its a string array instead of an int array? Any help appreciated!

Yes, this happens because it's array of Strings.
Default sorting for String type - simple Unicode ordering is similar to alphabetical sorting. That's why your result looks like that.
If you change type to int, everything should be fine.

Array.sort()'s sorting algorithm is set by its content's natural ordering (the content's implementation of the Comparable interface).
You can check a class' sort by going to the Java documentation and checking the class' implementation. For example, String's implementation (under String.compareTo(String)) specifies that this is done by lexicographical order (more commonly known as alphabetical order).
In order to fix this issue, add leading 0's to your other numbers, or use a different content type (like int).

Related

Sort integers having special character in Java

I have a problem where I need to sort Integers separated by hyphen either in ascending or descending order.
I tried using
Collections.sort(list, Collections.reverseOrder());
Where list is an instance of ArrayList created, but its not giving me the exact result.
The arrayList looks like this:
[91,95,96-1,94-2,94-1,100-2].
The expected way is:
[91,94-1,94-2,95,96-1,100-2]
Using the default sorting on Strings will use a lexicographical order, whereas you intend to sort the Strings in a numerical order (and if the first number is equal, by the second number). A way to accomplish this is by using two Comparators:
List<String> list = new ArrayList<>(Arrays.asList("96-1","91","94-2","100-2","94-1","95"));
System.out.println("Unsorted: "+list);
Comparator<String> primaryComparator =
(a,b)->Integer.valueOf(a.split("-")[0])
.compareTo(Integer.valueOf(b.split("-")[0]));
Comparator<String> secondaryComparator =
(a,b)->Integer.valueOf(a.split("-")[1])
.compareTo(Integer.valueOf(b.split("-")[1]));
list.sort(primaryComparator.thenComparing(secondaryComparator));
System.out.println("Sorted: "+list);
list.sort(primaryComparator.thenComparing(secondaryComparator).reversed());
System.out.println("Sorted in reverse: "+list);
Try it online.
As for the comparators themselves, I assumed the Strings in the list are always valid, and always of the form \d+(-\d+)?, so either an integer, or two integers separated with a hyphen. (If this is not the case, you might want to add some additional checks/validations with a custom Java 7 style comparator to make it more readable then the Java 8 style lambdas.)
The .split("-")[0] / .split("-")[1] will split this String on the hyphen, and takes either the first or last integer depending on the comparator. It will then convert this to an integer with Integer.valueOf(...), and will use the default integer comparing builtin Integer1.compareTo(Integer2).

How to increase efficiency

I have the following homework question:
Suppose you are given two sequences S1 and S2 of n elements, possibly containing duplicates, on which a total order relation is defined. Describe an efficient algorithm for determining if S1 and S2 contain the same set of elements. Analyze the running time of this method
To solve this question I have compared elemements of the two arrays using retainAll and a HashSet.
Set1.retainAll(new HashSet<Integer>(Set2));
This would solve the problem in constant time.
Do I need to sort the two arrays before the retainAll step to increase efficiency?
I suspect from the code you've posted that you are missing the point of the assignment. The idea is not to use a Java library to check if two collections are equal (for that you could use collection1.equals(collections2). Rather the point is to come up with an algorithm for comparing the collections. The Java API does not specify an algorithm: it's hidden away in the implementation.
Without providing an answer, let me give you an example of an algorithm that would work, but is not necessarily efficient:
for each element in coll1
if element not in coll2
return false
remove element from coll2
return coll2 is empty
The problem specifies that the sequences are ordered (i.e. total order relation is defined) which means you can do much better than the algorithm above.
In general if you are asked to demonstrate an algorithm it's best to stick with native data types and arrays - otherwise the implementation of a library class can significantly impact efficiency and hide the data you want to collect on the algorithm itself.

Custom Java sort by name

I want to sort something like this:
Given an ArrayList of objects with name Strings, I am trying to write the compareTo function such that Special T is always first, Special R is always second, Special C is always third, and then everything else is just alphabetical:
Special T
Special R
Special C
Aaron
Alan
Bob
Dave
Ron
Tom
Is there a standard way of writing this kind of compare function without needing to iterate over all possible combinations between the special cases and then invoking return getName().compareTo(otherObject).getName()); if it's a non-special case?
I would put the special cases in a HashMap<String, Integer> with the name as key and position as value. The advantages are:
search is in O(1) order of magnitude
The HashMap may be populated from an external source

Efficient data structure that checks for existence of String

I am writing a program which will add a growing number or unique strings to a data structure. Once this is done, I later need to constantly check for existence of the string in it.
If I were to use an ArrayList I believe checking for the existence of some specified string would iterate through all items until a matching string is found (or reach the end and return false).
However, with a HashMap I know that in constant time I can simply use the key as a String and return any non-null object, making this operation faster. However, I am not keen on filling a HashMap where the value is completely arbitrary. Is there a readily available data structure that uses hash functions, but doesn't require a value to be placed?
If I were to use an ArrayList I believe checking for the existence of some specified string would iterate through all items until a matching string is found
Correct, checking a list for an item is linear in the number of entries of the list.
However, I am not keen on filling a HashMap where the value is completely arbitrary
You don't have to: Java provides a HashSet<T> class, which is very much like a HashMap without the value part.
You can put all your strings there, and then check for presence or absence of other strings in constant time;
Set<String> knownStrings = new HashSet<String>();
... // Fill the set with strings
if (knownString.contains(myString)) {
...
}
It depends on many factors, including the number of strings you have to feed into that data structure (do you know the number by advance, or have a basic idea?), and what you expect the hit/miss ratio to be.
A very efficient data structure to use is a trie or a radix tree; they are basically made for that. For an explanation of how they work, see the wikipedia entry (a followup to the radix tree definition is in this page). There are Java implementations (one of them is here; however I have a fixed set of strings to inject, which is why I use a builder).
If your number of strings is really huge and you don't expect a minimal miss ratio then you might also consider using a bloom filter; the problem however is that it is probabilistic; but you can get very quick answers to "not there". Here also, there are implementations in Java (Guava has an implementation for instance).
Otherwise, well, a HashSet...
A HashSet is probably the right answer, but if you choose (for simplicity, eg) to search a list it's probably more efficient to concatenate your words into a String with separators:
String wordList = "$word1$word2$word3$word4$...";
Then create a search argument with your word between the separators:
String searchArg = "$" + searchWord + "$";
Then search with, say, contains:
bool wordFound = wordList.contains(searchArg);
You can maybe make this a tiny bit more efficient by using StringBuilder to build the searchArg.
As others mentioned HashSet is the way to go. But if the size is going to be large and you are fine with false positives (checking if the username exists) you can use BloomFilters (probabilistic data structure) as well.

Sorting a collection of songs by runtime

I have to make a program that sorts a collection of songs by runtime. I have to analyse a selection of songs, each with a "Title" string, a "Composer" string, and a "Running Time" integer. Input will be piped through stdin, and output will be in stdout.
Here's an example input:
3
&
Pink Frost&Phillipps, Martin&234933
Se quel guerrier io fossi&Puccini, Giacomo&297539
Non piu andrai&Mozart&234933
M'appari tutt'amor&Flotow, F&252905
And output:
Se quel guerrier io fossi&Puccini, Giacomo&297539
M'appari tutt'amor&Flotow, F&252905
Non piu andrai&Mozart&234933
I know I have to sort these by Running Time, but I'm not sure which sorting algorithm to use. By general knowledge, the two sorting algo's that come to mind are Merge Sort and Quicksort, because they seem to be the quickest on average. I also have the idea of using a Comparator to compare two "Running time" elements in a Collection.
Could someone please point me in the right direction?
The easiest way is to write a class to hold the above values, which implements Comparable interface (or you could write up your own Comparator). The compareTo method can check the runtime and return a value accordingly.
Then pass it up to Collections.sort() method. This method uses a optimized version of Merge Sort. You don't have to write your own sorting logic to handle it this way, and you can rely on the Java Platform to do it for you. Unless you need specific performance tuning of sorting method, I guess this is the simplest way to go (KISS - Keep It Simple, Stupid).
Excerpt from Java API Docs on Collections.sort (http://download.oracle.com/javase/1,5.0/docs/api/java/util/Collections.html#sort%28java.util.List%29):
The sorting algorithm is a modified mergesort (in which the merge is omitted if the highest element in the low sublist is less than the lowest element in the high sublist). This algorithm offers guaranteed n log(n) performance. This implementation dumps the specified list into an array, sorts the array, and iterates over the list resetting each element from the corresponding position in the array. This avoids the n2 log(n) performance that would result from attempting to sort a linked list in place.
Just stick to compareTo() method for String or int (running tittle) and use them in your Comparators. Nextly - use Collections.sort() which uses merge sort that is quite good :)
Ah and during runtime you should add those songs to list of songs - ArrayList or LinkedList. And sort them by Collections.sort(yourListName, new yourComparatorName());

Categories