I am trying to make kind of highscores in Java.
Basically I want a hashmap to hold the double value (so index starts from the highest double, so it's easier for me to sort highscores) and then the second value will be the client object, like this:
private HashMap<Double, TempClient> players = new HashMap<Double, TempClient>();
And to insert a new value:
TempClient client = new TempClient(kills, rank, deaths, name);
this.players.put(client.getKdr(), client);
Now, of course I can't iterate through the hashmap because it gets the list item by key, not index.
How can I iterate through a hashmap? or any good ideas for my case?
I tried it in a Foo class:
Output:
0.5
0.6
0.9
0.1
2.5
Code:
public class Foo {
public static void main(String[] args) {
HashMap<Double, String> map = new LinkedHashMap<Double, String>();
map.put(0.5, "hey");
map.put(0.6, "hey1");
map.put(0.9, "hey2");
map.put(0.1, "hey425");
map.put(2.5, "hey36");
for (Double lol : map.keySet()) {
System.out.println(lol);
}
}
}
You can iterate like this.
for (Double k : players.keySet())
{
TempClient p = players.get(k);
// do work with k and p
}
If you want to keep keys sorted, use e.g. a TreeMap.
If you want to keep the keys in the order you inserted
them in there, use e.g. a LinkedHashMap.
The best way is to iterate through hashmap is using EntrySet.
for (Map.Entry<Double, TempClient> entry : map.entrySet()) {
Double key= entry.getKey();
TempClient value= entry.getValue();
// ...
}
You'd be better off making your TempClient objects implement Comparable, adding them to a list, and then just using Collections.sort().
Since you can't sort items in a HashMap, nor you can sort them by value in a TreeMap you could use a TreeSet with a custom class:
class Score implements Comparable<Score>
{
final Player player;
final int score;
Score(Player player, int score) {
this.player = player;
this.score = score;
}
public int compareTo(Score other) {
return Integer.compare(this.score, other.score);
}
public int hashCode() { return player.hashCode(); }
public boolean equals(Object o) { return this.player.equals(...); }
}
TreeSet<Score> scores = new TreeSet<Score>();
score.add(new Score(player, 500));
for (Score s : scores) {
..
}
This will have both the advantages:
it will be iterable
it will keep scores automatically sorted
It should work easily with consistente between equals, hashCode and compareTo but maybe you should tweak something (since it's untested code).
Related
I have a HashMap that converts two Strings to words and then it adds the words to the map. I have it so that one key can point to multiple values. Now I'd like to make a loop that inverts the table so that all values point to keys. Don't bother with a key pointing to multiple values in the inverse.
Map<Word,Set<Word>> map = new HashMap<Word,Set<Word>>();
public void add(Word t, Word m) {
if(map.containsKey(t)) {
Set<Word> newM = map.get(t);
newM.add(m);
} else {
Set<Word> newSet = new HashSet<>();
newSet.add(m);
map.put(t, newSet);
}
}
public void add(String t, String m) {
add(new Word(t), new Word(m));
}
public Dictionary inverse() {
}
The main problem you're facing is the very common misuse of a map. In your case you don't realy have a map. You have something vaguely similar, so you deciced to use a map. What you really have is a Set of DictionaryEntry objects with DidctionaryEntry looking something like this:
public class DisctionaryEntry {
private String word;
private Set<String> translations;
}
using that datastructure and adding a addTranslation(String translation) method to it, I think, your question becomes fairly obvious.
So I have a HashMap looking like this :
HashMap<Movie, Float> movies;
It contains some movies with their global ratings as floats, and I want to sort the movies from the best to the worst.
I had a look in Collections.sort() but have no idea if I can do something with it...
It is not possible to sort a HashMap. If you need a sorted map take a look at TreeMap.
What about adding the rating value to the Movie class and let it implement Comparable?
public class Movie implements Comparable<Movie> {
private Float rating;
public Movie(Float rating) {
this.rating = rating;
}
public Float getRating() {
return rating;
}
public int compareTo(Movie param) {
return param.getRating().compareTo(rating);
}
#Override
public String toString() {
return String.valueOf(rating);
}
}
Then you can use your Movie class like this:
public static void main(String[] args) {
Set<Movie> movies = new HashSet<Movie>();
movies.add(new Movie(0.6f));
movies.add(new Movie(0.5f));
movies.add(new Movie(0.7f));
movies.add(new Movie(0.2f));
// Movie.class has to implement Comparable
System.out.println("First option:");
List<Movie> list = new ArrayList<Movie>(movies);
Collections.sort(list);
printMovies(list);
// Works without implementing Comparable in Movie.class
System.out.println("\nSecond option:");
List<Movie> secondList = new ArrayList<Movie>(movies);
Collections.sort(secondList, new Comparator<Movie>() {
public int compare(Movie movie1, Movie movie2) {
return movie2.getRating().compareTo(movie1.getRating());
}
});
printMovies(secondList);
}
private static void printMovies(List<Movie> list) {
for (Movie movie : list) {
System.out.println(movie);
}
}
Output:
First option:
0.7
0.6
0.5
0.2
Second option:
0.7
0.6
0.5
0.2
If you always want to sort the movies in the same way (from best to worse), I would choose the first option. If you always need different sort algorithms I would choose the second option, but even if your Movie class implements Comparable you can always provide a different Comparator as shown in the example.
use TreeMap. From this so answer
public class Testing {
public static void main(String[] args) {
HashMap<String,Double> map = new HashMap<String,Double>();
ValueComparator bvc = new ValueComparator(map);
TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc);
map.put("A",99.5);
map.put("B",67.4);
map.put("C",67.4);
map.put("D",67.3);
System.out.println("unsorted map: "+map);
sorted_map.putAll(map);
System.out.println("results: "+sorted_map);
}
}
class ValueComparator implements Comparator<String> {
Map<String, Double> base;
public ValueComparator(Map<String, Double> base) {
this.base = base;
}
// Note: this comparator imposes orderings that are inconsistent with equals.
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return -1;
} else {
return 1;
} // returning 0 would merge keys
}
}
HashMap is not the datastructure for what you want to achieve. you can read more about HashMap here for exmaple:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html
what I suggest for you is to include your rating within your Movie object and make a Comperator that can compare your Movie objects based on rating. place the Movie's in a ArrayList, then you can sort it with the comperator and Collections.sort
You can use the Guava library to do this - there is already an excellent answer on here explaining how to do this.
You could just use a TreeMap from the start. It is a sorted map, you just have to define a Comparator (in this case, use your floats)
If you want to stick to HashMaps, yes you can use Collections.sort. But again, you still have to learn how to use a Comparator.
HashMaps are unsorted by default. If you need ordering either use a TreeMap or simply sort into a List<Movie>
List<Movie> movies = new ArrayList<Movie>();
Collections.sort(movies, new Comparator<Movie>() {
public int compare(Movie m1, Movie m2) {
return m1.getRating() - m2.getRating();
}
});
I got an object Recipe that implements Comparable<Recipe> :
public int compareTo(Recipe otherRecipe) {
return this.inputRecipeName.compareTo(otherRecipe.inputRecipeName);
}
I've done that so I'm able to sort the List alphabetically in the following method:
public static Collection<Recipe> getRecipes(){
List<Recipe> recipes = new ArrayList<Recipe>(RECIPE_MAP.values());
Collections.sort(recipes);
return recipes;
}
But now, in a different method, lets call it getRecipesSort(), I want to sort the same list but numerically, comparing a variable that contains their ID. To make things worse, the ID field is of the type String.
How do I use Collections.sort() to perform the sorts in Java?
Use this method Collections.sort(List,Comparator) . Implement a Comparator and pass it to Collections.sort().
class RecipeCompare implements Comparator<Recipe> {
#Override
public int compare(Recipe o1, Recipe o2) {
// write comparison logic here like below , it's just a sample
return o1.getID().compareTo(o2.getID());
}
}
Then use the Comparator as
Collections.sort(recipes,new RecipeCompare());
The answer given by NINCOMPOOP can be made simpler using Lambda Expressions:
Collections.sort(recipes, (Recipe r1, Recipe r2) ->
r1.getID().compareTo(r2.getID()));
Also introduced after Java 8 is the comparator construction methods in the Comparator interface. Using these, one can further reduce this to 1:
recipes.sort(comparingInt(Recipe::getId));
1 Bloch, J. Effective Java (3rd Edition). 2018. Item 42, p. 194.
Create a comparator which accepts the compare mode in its constructor and pass different modes for different scenarios based on your requirement
public class RecipeComparator implements Comparator<Recipe> {
public static final int COMPARE_BY_ID = 0;
public static final int COMPARE_BY_NAME = 1;
private int compare_mode = COMPARE_BY_NAME;
public RecipeComparator() {
}
public RecipeComparator(int compare_mode) {
this.compare_mode = compare_mode;
}
#Override
public int compare(Recipe o1, Recipe o2) {
switch (compare_mode) {
case COMPARE_BY_ID:
return o1.getId().compareTo(o2.getId());
default:
return o1.getInputRecipeName().compareTo(o2.getInputRecipeName());
}
}
}
Actually for numbers you need to handle them separately check below
public static void main(String[] args) {
String string1 = "1";
String string2 = "2";
String string11 = "11";
System.out.println(string1.compareTo(string2));
System.out.println(string2.compareTo(string11));// expected -1 returns 1
// to compare numbers you actually need to do something like this
int number2 = Integer.valueOf(string1);
int number11 = Integer.valueOf(string11);
int compareTo = number2 > number11 ? 1 : (number2 < number11 ? -1 : 0) ;
System.out.println(compareTo);// prints -1
}
Use the method that accepts a Comparator when you want to sort in something other than natural order.
Collections.sort(List, Comparator)
Sort the unsorted hashmap in ascending order.
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2)
{
return o2.getValue().compareTo(o1.getValue());
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
I have an ArrayList that consists of an ArrayList that constists of Strings: ArrayList<ArrayList<String>>. How can I sort on the first entry of he inner ArrayList? For example I would like this:
a = [['1','apple'],['3','pear'],['2','banana'],['1',orange']]
to become:
a_sorted = [['1','apple'],['1','orange'],['2','banana'],['3','pear']]
The order of duplicate first entries (like apple and orange) do not matter. I've tried using Collections.sort(a,new ColumnComparator()) but it will not accept ArrayLists. This is the class I used:
public class ColumnComparator implements Comparator<ArrayList<String>>{
public int compare(ArrayList<String> ar1, ArrayList<String> ar2){
return ar1.get(0).compareTo(ar2.get(0));
}
}
Instead of storing an Array of an Array, why don't you create a custom Class that implements Comparable. eg.
class Fruit implements Comparable<Fruit> {
protected int number;
protected String name;
public Fruits(int number, String name) {
this.number = number;
this.name = name;
}
#Override
public int compareTo(Fruit f) {
return number < f.number;
// or depending on if ascending or descending order wanted
// return number > f.number
}
}
Then to sort just run Collections.sort(a). This way is flexible and easily extended.
You can create a Map <String, ArrayList<String>> with first entry of the ArrayLists as key and the ArrayList itself as value. Then sort the Map (use Sorted Map or a Comparator to sort on the Map keys) on keys and you will get what you want.
Why cant you use a this ArrayList<Map<String,String>> instead of ArrayList<ArrayList<String>>. You can easily sort the Map on the key by using TreeMap.
Note: This will only work if you have only two entries in your inner arraylist.
If you really want to do it that way, you can try this:
import java.util.Comparator;
public class ColumnComparable implements Comparator<ArrayList<String>>{
#Override
public int compare(ArrayList<String> o1, ArrayList<String> o2) {
return (Integer.parseInt(o1.get(0)) > Integer.parseInt(o2.get(0)) ? -1 : (Integer.parseInt(o1.get(0)) == Integer.parseInt(o2.get(0)) ? 0 : 1));
}
}
The code was found here.
I have a 2D string array consisting of values like as
{ "Home","0.1256784"
"Contact","-0.56789"
"Refer","1.36589"
"Next","3.678456" }
I have to sort the array based upon the second element(double value) and obtain a result such as like
{"Contact","-0.56789"
"Home","0.1256784"
"Refer","1.36589"
"Next","3.678456" }
I have used some bubble sort code to sort it and it works, but and i have to know how can i make the sorting more efficient than my one in faster manner.I tried some code posted previously for the questions related to mine but i can't get the task done.
My Code:
String tt="",tk="";
for(int i=1;i<myarray.length;i++)
{
for(int j=1;j<myarray.length-1;j++)
{
if(Double.parseDouble(myarray[i][1])<Double.parseDouble(myarray[j][1]))
{
tk=myarray[i][1];
tt=myarray[i][0];
myarray[i][1]=myarray[j][1];
myarray[i][0]=myarray[j][0];
myarray[j][1]=myarray;
myarray[j][0]=myarray;
}
}
}
public class Sort2D {
public static void main(String args[]) {
String ss[][] = {
{"Home", "0.1256784"},
{"Contact", "-0.56789"},
{"Refer", "1.36589"},
{"Next", "3.678456"}
};
Arrays.sort(ss, new Comparator<String[]>() {
public int compare(String[] s1, String[] s2) {
double d1 = Double.parseDouble(s1[1]);
double d2 = Double.parseDouble(s2[1]);
return Double.compare(d1, d2);
}
});
for (String[] s : ss) {
System.out.println(s[0] + ": " + s[1]);
}
}
}
If it's a 2d array you can use Array.sort(String[], Comparator<String[]> comparator) and pass a custom comparator, which compares the 2nd element of the sub array.
You can use Arrays.sortsort(Object[] a, Comparator c) and let java take care of it. You may find this link useful
Alternative approach: you could copy the data to a TreeMap (in case all double values are unique) and let the map to the sorting:
Map<Double, String> map = new TreeMap<Double, String>();
for (String[] row:myArray) {
map.put(Double.parseDouble(row[1]), row[1]);
The entrysets iterator now returns the values in ascending sort order.