Reputation: 3587
I don't know why my list is not sorted.
I'm using Collection.sort, it seems to do the job but when I launch the UnitTest it outputs an error.
Expected :characterWithMaxVotes [voteCount : 100]
Actual :characterMiddle75[voteCount : 75]
//Exact same method as in the Character class (pasted for better readability on SO question)
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
@Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() > p1.getVoteCount()) ? 1 : 0;
return result;
}
});
}
@Test
public void sortCharactersByVoteCounts() {
Character characterWithMinVotes = Character.newBuilder().name("characterWithMinVotes").voteCount(0).build();
Character characterMiddle25 = Character.newBuilder().name("characterMiddle25").voteCount(25).build();
Character characterMiddle75 = Character.newBuilder().name("characterMiddle75").voteCount(75).build();
Character characterWithMaxVotes = Character.newBuilder().name("characterWithMaxVotes").voteCount(100).build();
List<Character> lstCharacters = new ArrayList<>();
lstCharacters.add(characterMiddle75);
lstCharacters.add(characterWithMaxVotes );
lstCharacters.add(characterMiddle25);
lstCharacters.add(characterWithMinVotes);
sortCharactersByVotes(lstCharacters);
System.out.print(lstCharacters);
assertEquals(lstCharacters.get(0), characterWithMaxVotes);
assertEquals(lstCharacters.get(1), characterMiddle75);
assertEquals(lstCharacters.get(2), characterMiddle25);
assertEquals(lstCharacters.get(3), characterWithMinVotes);
}
How to do it properly, thank you for your help.
PS : as requested, here is my Character class
public class Character {
private static final String TAG = "Character";
private int id;
private String name = "";
public int voteCount;
public boolean isVotedByUser = false;
public int getId() {
return id;
}
public int getVoteCount() {
return voteCount;
}
public String getName() {
return name;
}
public static CharacterBuilder newBuilder(){
return new CharacterBuilder();
}
@Override
public String toString() {
return name + "[voteCount : " + voteCount + "]";
}
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
@Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() > p1.getVoteCount()) ? 1 : 0;
return result;
}
});
}
public static class CharacterBuilder {
public Character character;
CharacterBuilder() {
character = new Character();
}
public CharacterBuilder id(int id) {
character.id = id;
return this;
}
public CharacterBuilder name(String name) {
character.name = name;
return this;
}
public CharacterBuilder voteCount(int voteCount) {
character.voteCount = voteCount;
return this;
}
public Character build() {
return character;
}
}
}
Upvotes: 2
Views: 236
Reputation: 45005
The implementation of your Comparator
is not correct, as you want to have highest value first (and not the opposite lowest value first), you are supposed to return a positive value if character.getVoteCount() < p1.getVoteCount()
and a negative value if character.getVoteCount() > p1.getVoteCount()
, you should use Integer.compare(int x, int y)
to compare the values of getVoteCount()
(assuming that it returns an int
) such that your Comparator
could be :
new Comparator<Character>() {
@Override
public int compare(Character c1, Character c2) {
return Integer.compare(c2.getVoteCount(), c1.getVoteCount());
}
}
NB: Don't compare the values of getVoteCount()
with a simple subtraction otherwise you will take the risk to get incorrect results as it is prone to overflow issues.
Upvotes: 3
Reputation: 1484
(edited to use Integer.compare
as suggested)
The compare
method must return 0 if and only if the two compared objects have equal "rank" (in your case, equal vote count), otherwise must return a positive value if a>b or negative if b>a (or vice versa, according to the wanted sort direction).
To solve this simply, you can write (assuming getVoteCount()
is int
):
public int compare(Character character, Character p1) {
return Integer.compare(p1.getVoteCount(), character.getVoteCount());
}
(to reverse the sort result, just swap the operands)
Upvotes: 3
Reputation: 32036
You sort of comparison method shall be modified to
public static void sortCharactersByVotes(List<Character> lstCharacters) {
lstCharacters.sort(Comparator.comparingInt(Character::getVoteCount));
}
Note - The comparison is based on the integer getVoteCount
of Character
and this is supported in Java 8+.
Upvotes: 0
Reputation: 1234
I think that is better to change a little bit the comparator implemented. Try:
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
@Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() - p1.getVoteCount());
return result;
}
});
}
Another thing is that you are adding twice the
characterWithMaxVotes
Hope it helps!
Upvotes: 1