Sort a ArrayList<String> by number value - java

I have an ArrayList of video resolutions that looks like this:
"1024x768", "800x600", "1280x1024", etc
I want to sort it based on numeric value in first part of string.
Ie, the above would sort out to look like this:
"800x600","1024x768","1280x1024"
Is there a quick and dirty way to do this, by that I mean in less then 2-3 lines of code? If not, what would be the proper way? The values I get are from an object not my own. It does have a getWidth() and getHeight() methods that return ints.

If the objects in the array are Resolution instances with getWidth methods then you can use a Comparator to sort on those:
Collections.sort(resolutions, new Comparator {
public int compare(Resolution r1, Resolution r2) {
return Integer.valueOf(r1.getWidth()).compareTo(Integer.valueOf(r2.getWidth()));
}
});

The proper way is to write a Comparator implementation that operates on Strings, except that it parses up to the first non-numeric character. It then creates an int out of that and compares the ints.
You can then pass an instance of that Comparator into Collections.sort() along with your List.

Use a custom Comparator to sort the ArrayList via the Collections api.
Collections.sort(resolutionArrayList, new ResolutionComparator())

Using a Comparator will work, but will get slow if you have lots of values because it will parse each String more than once.
An alternative is to add each value to a TreeMap, with the number you want as the key, i.e., Integer.valueOf(s.substring(0,s.indexOf('x'))), then create a new ArrayList from the sorted values in treeMap.values().

The solution suggested by Shadwell in his answer is correct and idiomatic.
But if you're looking for a more concise solution, then I'd advise you use lambdaj which will enable you to write code like:
List<Resolution> sortedResolutions = sort(resolutions, on(Resolution.class).getWidth());

Related

How to create ArrayList without using add-function

As the title implies, I'd like to know how to insert different values into my ArrayList, without using too much space for several "add" functions.
ArrayList<Integer> arr = new ArrayList<Integer>(Arrays.asList(3,4));
ArrayCheck.allDivisibleBy(arr, divisor);
I have got an arraylist called arr, and I don't know if this is the right way to add several values (3,4) that way.
Furthermore I would also like to check the values in another method called allDivisbleBy. The function of this method is not relevant though, but I want to check the values and am not sure if "ArrayCheck" is a way to send the array values to the method.
The simplest way is to use Arrays.asList(arr). As expected, that static method returns a List with as it's contents the elements of the array.
I don't know if this is the right way to add several values (3,4) that
way
Yes it is. Else you can use this:
ArrayList<Integer> arr = new ArrayList<Integer>(2);
arr.add(3);
arr.add(4);
I want to check the values and am not sure if "ArrayCheck" is a way to
send the array values to the method
ArrayCheck is not a standard java class.
Check all of your inputs for your condition, put them in a Collection and use method addAll instead of add to add all of collection items at once.

How to shuffle/randomize elements within EnumSet in Java?

I have an EnumSet like this:
EnumSet<Fruit> otherFruits = EnumSet.complementOf(CURRENT_FRUIT);
I want to shuffle elements within otherFruits.
Is there any way to shuffle/randomize elements within this EnumSet? I don't want to convert it to List if possible. Can anyone provide an example as well.
I am using Java 7.
No, it's not possible to do this without conversion to another data type like array or list. Internally EnumSet does not preserve an order: it just stores a bitmask of used enum constants. This way it's much faster and takes very low amount of memory.
To solve your problem you can use ArrayList:
List<Fruit> fruits = new ArrayList<>(otherFruits);
Collections.shuffle(fruits);
Sets don't have a modifiable order. You'll need to convert this to a List or other collection type that does.

Is it better to use a TreeSet or ArrayList when using a custom comparator

I have implemented a graph.
I want to sort a given subset of vertices with respect to their degrees.
Therefore, I've written a custom comparator named DegreeComparator.
private class DegreeComparator implements Comparator<Integer>
{
#Override
public int compare(Integer arg0, Integer arg1)
{
if(adj[arg1].size() == adj[arg0].size()) return arg1 - arg0;
else return adj[arg1].size() - adj[arg0].size());
}
}
So, which one of the below is more efficient?
Using TreeSet
public Collection<Integer> sort(Collection<Integer> unsorted)
{
Set<Integer> sorted = new TreeSet<Integer>(new DegreeComparator());
sorted.addAll(unsorted);
return sorted;
}
Using ArrayList
Collections.sort(unsorted, new DegreeComparator());
Notice that the second approach is not a function, but a one-line code.
Intuitively, I'd rather choose the second one. But I'm not sure if it is more efficient.
Java API contains numerous Collection and Map implementations so it might be confusing to figure out which one to use. Here is a quick flowchart that might help with choosing from the most common implementations
A TreeSet is a Set. It removes duplicates (elements with the same degree). So both aren't equivalent.
Anyway, if what you want naturally is a sorted list, then sort the list. This will work whether the collection has duplicates or not, and even if it has the same complexity (O(n*log(n)) as populating a TreeSet, it is probably faster (because it just has to move elements in an array, instead of having to create lots of tree nodes).
If you only sort once, then the ArrayList is an obvious winner. The TreeSet is better if you add or remove items often as sorting a list again and again would be slow.
Note also that all tree structures need more memory and memory access indirection which makes them slower.
If case of medium sized lists, which change rather frequently by a single element, the fastest solution might be using ArrayList and inserting into the proper position (obviously assuming the arrays get sorted initially).
You'd need to determine the insert position via Arrays.binarySearch and insert or remove. Actually, I would't do it, unless the performance were really critical and a benchmark would show it helps. It gets slow when the list get really big and the gain is limited as Java uses TimSort, which is optimized for such a case.
As pointed in a comment, assuring that the Comparator returns different values is sometimes non-trivial. Fortunately, there's Guava's Ordering#arbitrary, which solves the problem if you don't need to be compatible with equals. In case you do, a similar method can be written (I'm sure I could find it somewhere if requested).

Store String+Integer pair in dynamic array?

I need to store few data pairs in array. Maybe few dozens. I only need to append, no need to delete, no need to search. Then I will access by index. Each pair is String value and Integer value. Java provides so many way to do this, which is the common practice for something like that? Two arrays? A class in an array?
I know how to do this in JavaScript:
var data = []
data.push(['Some name', 100])
//somewhere else
data.push(['Other name', 200])
but I need a solution for Java
Thank you.
For example you can create Pair class (or use implementations from apache commons) to store two elements in List.
List<Pair<String, Integer>> l = new ArrayList<>();
l.add(new Pair<String, Integer>("Some name", 100));
See Generic pair class and Java Pair<T,N> class implementation to see how you can implement Pair class.
It really depends, but in general I think it is better to create an object and use a list of it:
public class MyObject {
private String myString;
private Integer myInt;
// getters setters
}
And use:
List<MyObject> = new ArrayList<>();
(you can also use Pair instead)
If the strings (or ints) are unique, you can use Map, but it is harder to get the insert index.
Another option is just two lists, one for Strings, one for Integers, and use same index in both lists.
I go by using POJO as suggested above for this as this helps to define getter and setter for all the attributes of POJO, compare the objects by overriding equals and hashCode methods. By using getter and setter you know what is stored in what field and comparison can provide you sorting of objects as per your requirements. So this approach is cleaner and extensible for accommodating new requirements too. Also as you are putting data with sequential key so each instance of Pojo can be put in List (if required in sorted order.

Constructing an if statement that checks enums on a list

What would be the most efficent to check if something is on a list of enums? I've looked around for a while and it wasn't very clear. Arrays don't have a contains() function and hashmaps are key:value.
Something like:
if(enumlist.contains(foo.enum())){
// Do something
}
Use List#indexOf().
if (enumList.indexOf(foo) > -1) {
// go crazy
}
Alternately, you can use the (extremely efficient) EnumSet data structure to store the objects — if you're okay with not being able to store duplicate elements.
if (enumSet.contains(foo)) {
// just, like, whatever, man
}
EnumSet has a suitable contains() method.
Addendum: Using this example, the following prints true.
System.out.println(Resolution.deluxe.contains(Resolution.RES_256));

Categories