Using Super Class and Extend From It - java

I want to sort some team base on their points (win: 3 points, draw: 1 points and defeat: 0 points). I have an array which contains some teams' names and their results, I have extracted their scores and then sorted them descending. Here is the code I have used:
import java.util.*;
import java.util.Map.Entry;
public class SCAN{
public static void main(String[] args) {
Map<String, Integer> points = new HashMap<>();
String[] challenges = new String[]{
"Team(A) 2 - 1 Team(C)",
"Team(D) 3 - 1 Team(A)",
"Team(B) 3 - 3 Team(D)",
"Team(C) 0 - 4 Team(B)",
"Team(B) 2 - 0 Team(A)"
};
calcualte(challenges, points);
List<Entry<String, Integer>> entries = new ArrayList<Entry<String, Integer>>(
points.entrySet());
Collections.sort(entries, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> e1,
Entry<String, Integer> e2) {
return e2.getValue().compareTo(e1.getValue()); // Sorts
// descending.
}
});
Map<String, Integer> orderedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : entries) {
orderedMap.put(entry.getKey(), entry.getValue());
}
for (Entry<String, Integer> element : entries) {
System.out.println(element);
}
}
private static void calcualte(String[] challenges, Map<String, Integer> points) {
List<String> challengeList = new ArrayList<>();
for (String str : challenges) {
String[] bits = str.trim().split(" ");
String firstTeam = bits[0];
String lastTeam = bits[bits.length - 1];
if (!challengeList.contains(firstTeam)) {
challengeList.add(firstTeam);
}
if (!challengeList.contains(lastTeam)) {
challengeList.add(lastTeam);
}
int firstScore = Integer.parseInt(bits[1]);
int lastScore = Integer.parseInt(bits[3]);
if (firstScore > lastScore) {
insert(3, points, firstTeam);
insert(0, points, lastTeam);
} else if (firstScore < lastScore) {
insert(3, points, lastTeam);
insert(0, points, firstTeam);
} else {
insert(1, points, firstTeam);
insert(1, points, lastTeam);
}
{
}
}
}
private static void insert(int i, Map<String, Integer> points, String team) {
int score = points.containsKey(team) ? points.get(team) : 0;
score += i;
points.put(team, score);
}
}
I know this, but I should do it by using a superclass So I need a subclass which its name is Plays and should be extended from a super class which its name is Playclass . The Playclass should not be changed. This class needs three abstracted method which should be overridden, they are won(),drawn() and defeated(). The other method which should to be overridden, is Print() which shows each team's information, like bellow:
public abstract class Playclass {
private String name;
Playclass(String name){
this.name=name;
}
public String getName() {
return name;
}
public abstract void print();
public abstract void won();
public abstract void drawn();
public abstract void defeated();
}
The main class name could be Playleage and it should contain the String[] challenges = new String[]{…} which I showed in the first code. I know how to sort them base on their scores (like the first code) but I don’t know how to use the classes which I said. May someone help me? thanks

Related

How to iterate over a list of Map of Strings and add to another list if map contains matching elements on a key value?

I have a List of Map<String, String> that I want to iterate over and find the common elements inside the map of string and add to another map.
I am confused what should go inside the if loop to get my expected output. I am looking for comparator type call but I couldn't find that anywhere.
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i).get("Journal ID").equals(list.get(i+1).get("Journal ID")))
// ???
}
}
I was using this method to sort list of Maps. I am expecting some thing like this
public Comparator<Map<String, String>> mapComparator = new Comparator<>() {
public int compare(Map<String, String> m1, Map<String, String> m2) {
return m1.get("Journal ID").compareTo(m2.get("Journal ID"));
}
}
Collections.sort(list, mapComparator);
// input and the expected output
my List = [{Journal ID=123, featureID=312},{Journal ID=123, featureID=313},{Journal ID=134,
featureID=314},{Journal ID=123, featureID=1255}]
expected output is one that matching the "Journal ID" [{Journal ID=123, featureID=312},
{ Journal ID=123, featureID=313},{Journal ID=123, featureID=1255}].
One approach is to construct a second map which will aggregate all maps.
It will reflect all keys form all maps. As value will be a list of each key value with counters. Implementation can be enhanced also, but the main aspect is how to proceed. Having the aggregate map, then is straight forward to transform in what ever structure needed.
public class TestEqMap {
public static void main(String[] args)
{
Map<String, String> m1 = Map.of("a","a1","b","b1");
Map<String, String> m2 = Map.of("a","a1","b","b2");
Map<String, String> m3 = Map.of("a","a2","b","b2");
Map<String, String> m4 = Map.of("a","a1","b","b2");
Map<String, String> m5 = Map.of("a","a3","b","b2");
AggMap amap = new AggMap();
amap.addMap(m1);
amap.addMap(m2);
amap.addMap(m3);
amap.addMap(m4);
amap.addMap(m5);
amap.map.forEach((k,v)->System.out.println("key="+k+"\n"+v));
}
static class AggMap
{
public Map<String, ListItem> map = new HashMap<String,ListItem>();
public void addMap(Map<String,String> m)
{
for(String key: m.keySet())
{
if(this.map.containsKey(key))
{
this.map.get(key).addItem(m.get(key));
}
else
{
ListItem li = new ListItem();
li.addItem(m.get(key));
this.map.put(key, li);
}
}
}
}
static class ListItem
{
public List<Item> li = new ArrayList<Item>();
public ListItem() {};
public void addItem(String str)
{
for(Item i: this.li)
{
if(i.val.equals(str))
{
i.count++;
return;
}
}
this.li.add(new Item(str));
}
public String toString()
{
StringBuffer sb= new StringBuffer();
this.li.forEach(i->sb.append(i+"\n"));
return sb.toString();
}
}
static class Item
{
public String val;
public int count=1;
public Item(String val)
{
this.val = val;
}
public String toString()
{
return "val="+this.val+" count="+this.count;
}
}
}
Output:
key=a
val=a1 count=3
val=a2 count=1
val=a3 count=1
key=b
val=b1 count=1
val=b2 count=4

ClassCastException when using TreeMap

I have a TreeMap<Integer, TreeMap<int[][], Integer>> jungle. When I try to execute the statements
TreeMap<int[][], Integer> tempMap = new TreeMap();
int[][] matrix = {{1}};
tempMap.put(matrix, 4);
this last line gives me the
java.lang.ClassCastException: [[I cannot be cast to java.base/java.lang.Comparable at java.base/java.util.TreeMap.compare
exception. Am I not allowed to use an int[][] as a key in a treeMap?
The purpose of a TreeMap is to have an ordered collection
A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
You must pass a Comparator that deals with int[][]; here an example with one that sorted based on the full sum of the array
class Custom2DArrayComparator implements Comparator<int[][]> {
private static int sum(int[][] v) {
return Arrays.stream(v).map(arr -> Arrays.stream(arr).sum())
.mapToInt(Integer::intValue).sum();
}
#Override
public int compare(int[][] o1, int[][] o2) {
return Integer.compare(sum(o1), sum(o2));
}
}
Use
public static void main(String[] args) {
TreeMap<int[][], Integer> tempMap = new TreeMap<>(new Custom2DArrayComparator());
int[][] matrix = {{1}};
tempMap.put(matrix, 4);
}
You can use the anonymous class to avoid creating a one outside
public static void main(String[] args) {
TreeMap<int[][], Integer> tempMap = new TreeMap<>(new Comparator<>() {
#Override
public int compare(int[][] o1, int[][] o2) {
return Integer.compare(sum(o1), sum(o2));
}
int sum(int[][] v) {
return Arrays.stream(v).map(arr -> Arrays.stream(arr).sum())
.mapToInt(Integer::intValue).sum();
}
});
int[][] matrix = {{1}};
tempMap.put(matrix, 4);
}
You'll need to implement your own logic in order for your key to be Comparable, as Johannes' comment points out. You could create a class that implements Comparator and pass it as argument at the initialization of the TreeMap.
Note that the default/overriden compare method would also be valid, as arrays are just Objects.
You could even implement all the logics for non-comparable Object keys you wish to insert in different Maps in a single class:
public class NonCompObjectKeyComparator implements Comparator<Object>
{
#Override
public int compare(Object o1, Object o2)
{
if (o1 instanceof int[][])
{
//((int[][])o1),((int[][])o2)//
}
else if (o1 instanceof String[])
{
//((String[])o1),((String[])o2)//
}
else if (o1 instanceof <OtherNonComparableObjType>)
{
//...
}
//...
return 0;
}
}
And then you got your überComparator there:
Comparator<Object> maCompa = new NonCompObjectKeyComparator();
TreeMap<int[][], Integer> tempMap = new TreeMap(maCompa);
TreeMap<String[], String> sArrayMap = new TreeMap(maCompa);
int[][] matrix = {{1}};
tempMap.put(matrix, 4);
String[] sKey = {"a"};
sArrayMap.put(sKey, "anotherWierdMap");
In order to create an specific int[][] comparator, just:
public class CustomKeyComparator implements Comparator<int[][]> {
public int compare(int[][] a1, int[][] a2) {
//your logic here
return 0;
}
}
and
TreeMap<int[][], Integer> tempMap = new TreeMap(new CustomKeyComparator());
int[][] matrix = {{1}};
tempMap.put(matrix, 4);

binarySearch with generics and capture of

I have a Task:
public interface Task {
}
Then I have implementations for those:
public interface Task__Init extends Task {
void init(Element e);
}
public interface Task__Hit_Test extends Task {
boolean hit_test(Element e, float x, float y);
}
public interface Task__Draw extends Task {
void draw(Element e);
}
I also have a class that can hold a instance of those implementations:
static public class Task_Holder<T extends Task> {
public int task_id;
public Task_Type type;
public T task;
// ...
}
Then I have a class that holds those, where the last ArrayList holds all of them (all_task_holders)
static public class Implementation_Context {
public HashMap<String, ArrayList<Task_Holder<Task__Init>>> init_solvers = new HashMap<>();
public HashMap<String, ArrayList<Task_Holder<Task__Draw>>> draw_solvers = new HashMap<>();
public HashMap<String, ArrayList<Task_Holder<Task__Hit_Test>>> hit_test_solvers = new HashMap<>();
public ArrayList<Task_Holder<? extends Task>> all_task_holders = new ArrayList<>();
// ...
}
Now one of the problem arises:
static public Task_Holder<?> find_task_holder(int task_id) {
Comparator<Task_Holder<?>> comparator = (a, b)-> {
if (a.task_id < b.task_id) return -1;
if (a.task_id > b.task_id) return 1;
return 0;
};
Collections.sort(ctx.implementation.all_task_holders, comparator);
Task_Holder<?> key = new Task_Holder<>();
key.task_id = task_id;
int index = Collections.binarySearch(ctx.implementation.all_task_holders, key);
for (Task_Holder<?> th : ctx.implementation.all_task_holders) {
if (th.task_id == task_id) {
return th;
}
}
assert false; // should we find things that are not there?
return null;
}
For the binarySearch I get (I make it a codeblock here, else stackoverflow removes words for some reason?):
The method binarySearch(List<? extends Comparable<? super T>>,
T) in the type Collections is not applicable for the arguments
(ArrayList<sfjl_ui.Task_Holder<?>>, sfjl_ui.Task_Holder<capture#6-of
?>)
I have no clue how to fix this. Every attempt breaks other things (for example I break the sort that's 3 lines higher).
It feels like paying off credit card debts with other credit cards, you never win.
How can I fix this?
Pass the comparator as an additional argument:
int index = Collections.binarySearch(ctx.all_task_holders, key, comparator);

LinkedHashMap<double[], Integer>, cannot access Integer with .get or .containsKey

I have a series of small arrays (consisting of two doubles), many of which are
the same. E.g.
{5.0, 15.0}
{5.0, 15.0}
{5.0, 15.0}
{12.0, 8.0}
{10.0, 8.0}
{10.0, 8.0}
I want to be able to count the number of each arrays, i.e.
3 of {5.0, 15.0}
1 of {12.0, 8.0}
2 of {10.0, 8.0}
To do this, I tried making use of a LinkedHashMap (linked, because the order
might come into use later on):
import java.util.Map;
import java.util.LinkedHashMap;
public class MapArrayInt {
Map<double[], Integer> arrays = new LinkedHashMap<double[], Integer>();
public static void main(String[] args) {
MapArrayInt mapArrayInt = new MapArrayInt();
mapArrayInt.addArray(5.0, 15.0);
mapArrayInt.addArray(5.0, 15.0);
mapArrayInt.addArray(5.0, 15.0);
mapArrayInt.addArray(12.0, 8.0);
mapArrayInt.addArray(10.0, 8.0);
mapArrayInt.addArray(10.0, 8.0);
System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{5.0, 15.0})));
System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{12.0, 8.0})));
System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{10.0, 8.0})));
}
void addArray(double val1, double val2) {
double[] newArray = new double[]{val1, val2};
if (!arrays.containsKey(newArray)) {
arrays.put(newArray, 1);
} else {
arrays.put(newArray, arrays.get(newArray) + 1);
}
}
}
I expected this output,
3
1
2
but got,
null
null
null
I'm quite new to Java, but I suspect this might be because each double[] counts as a unique because they are different instances, even though they contain the same two doubles.
How can I fix this, if I should at all (is there a better way)? I just need a data structure that allows me to
Add doubles[]
Preserves order of doubles[]
Easily iterate through to get doubles[] and number of said doubles[]
As I stated in my comment, with new you're creating a new instance of an object. Which means that the arrays you added with mapArrayInt.addArray(5.0, 15.0); and the arrays in mapArrayInt.arrays.get(new double[]{5.0, 15.0}) reference different objects. That's why you get null, because for the map those are different keys.
In order to circumvent this, you could create a custom wrapper class
import java.util.Arrays;
public class Exercise {
private final double[] array;
public Exercise(double first, double second) {
this.array = new double[]{first, second};
}
public boolean equals(Object obj) {
if(!(obj instanceof Exercise)) {
return false;
}
Exercise other = (Exercise)obj;
return Arrays.equals(this.array, other.array);
}
public int hashCode() {
return Arrays.hashCode(array);
}
}
The equals and hashCode methods are important, when you want to use this class in collections like Map, otherwise the hashcode of Object is used for checking equality and you'd have the same problem as you have now.
Then, in your main class you can use it like so:
void addArray(double val1, double val2) {
Exercise exercise = new Exercise(val1, val2);
if (!arrays.containsKey(exercise)) {
arrays.put(exercise, 1);
} else {
arrays.put(exercise, arrays.get(exercise) + 1);
}
}
And System.out.println(String.valueOf(mapArrayInt.arrays.get(new Exercise(5.0, 15.0))));
EDIT:
I changed one of the doubles to int (you said you're representing reps and weight ... and reps can only be a natural number right?)
You could build create an Exercise-Class like below and use the static method "of" to create the instances:
package somepackage;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
public class Exercise
{
private static final Map<Integer, Map<Double, WeakReference<Exercise>>> instances = new HashMap<>();
private final int reps;
private final double weight;
private Exercise(int reps, double weight)
{
this.reps = reps;
this.weight = weight;
}
public static Exercise of(int reps, double weight)
{
if (!instances.containsKey(reps))
{
instances.put(reps, new HashMap<>());
}
Map<Double, WeakReference<Exercise>> innerMap = instances.get(reps);
WeakReference<Exercise> weakRef = innerMap.get(weight);
Exercise instance = null;
if (weakRef != null)
{
instance = weakRef.get();
}
if (weakRef == null || instance == null || weakRef.isEnqueued())
{
instance = new Exercise(reps, weight);
innerMap.put(weight, new WeakReference<>(instance));
}
return instance;
}
public int getReps()
{
return this.reps;
}
public double getWeight()
{
return this.weight;
}
}
And then you could put those exercises in a map like below:
public void addArray(int reps, double weight)
{
Exercise exercise = Exercise.of(reps, weight);
if (!arrays.containsKey(exercise))
{
arrays.put(exercise, 1);
}
else
{
arrays.put(exercise, arrays.get(exercise) + 1);
}
}
OR:
Instead of an double[] as key you can use the a Map<Double, Integer> as your value for 2 values:
package somepackage;
import java.util.HashMap;
import java.util.Map;
public class MapArrayInt
{
private final Map<Double, Map<Double, Integer>> values;
public MapArrayInt()
{
this.values = new HashMap<>();
}
public void addArray(double val1, double val2)
{
if (!this.values.containsKey(val1))
{
this.values.put(val1, new HashMap<>());
}
Map<Double, Integer> innerValues = this.values.get(val1);
if (innerValues.containsKey(val2))
{
innerValues.put(val2, innerValues.get(val2) + 1);
}
else
{
innerValues.put(val2, 1);
}
}
public int getArrayValue(double val1, double val2)
{
Map<Double, Integer> innerValues = this.values.get(val1);
if (innerValues == null)
{
// you may also throw an Exception here
return 0;
}
Integer value = innerValues.get(val2);
if (value == null)
{
// also here you may throw an Exception
return 0;
}
return value;
}
public int getArrayValue(double[] values)
{
return getArrayValue(values[0], values[1]);
}
}

sort and group a java collection

I have an object which has a name and a score. I would like to sort a collection of such objects so that they are grouped by name and sorted by maximum score in each group (and within the group by descending score as well).
let me demonstrate what I intend to achieve. assume I have these objects(name, score):
(a, 3)
(a, 9)
(b, 7)
(b, 10)
(c, 8)
(c, 3)
then I would like them to be sorted like this:
(b, 10)
(b, 7)
(a, 9)
(a, 3)
(c, 8)
(c, 3)
is this feasible with a Comparator? I can't figure it out, so any hints would be appreciated.
No, you can't do it with a single sort with a single Comparator.
You have to:
group by name
sort the groups, by highest score in group
Then you need to flatten the groups back to a list.
With Java 8
Edit: Since i wrote this answer, Java 8 has come out, which simplifies the problem a lot:
import java.util.*;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;
List<Record> result = records.stream()
.sorted(comparingInt(Record::getScore).reversed())
.collect(groupingBy(Record::getName, LinkedHashMap::new, toList()))
.values().stream()
.flatMap(Collection::stream)
.collect(toList());
First we sort by score reversed, and then we group using a LinkedHashMap, which will preserve the insertion order for the keys, so keys with higher score will come first.
Sorting first is OK if the groups are small, so the redundant compares between objects in different groups don't hurt so much.
Also, with this method, duplicates are preserved.
Alternatively, if you don't care about preserving duplicates, you can:
Comparator<Record> highestScoreFirst = comparingInt(Record::getScore).reversed();
List<Record> result = records.stream()
.collect(groupingBy(Record::getName,
toCollection(() -> new TreeSet<>(highestScoreFirst))))
.values().stream()
.sorted(comparing(SortedSet::first, highestScoreFirst))
.flatMap(Collection::stream)
.collect(toList());
Where the records are grouped into sorted TreeSets, instead of sorting the values as the first operation of the stream, and then the sets are sorted by their first, highest value.
Grouping before sorting is appropriate if the groups are big, to cut down on redundant compares.
Implementing Comparable:
And you can make it shorter by having your record implement Comparable
public class Record implements Comparable<Record> {
#Override
public int compareTo(Record other) {
// Highest first
return -Integer.compare(getScore(), other.getScore());
/* Or equivalently:
return Integer.compare(other.getScore(), getScore());
*/
}
...
}
List<Record> result = records.stream()
.collect(groupingBy(Record::getName, toCollection(TreeSet::new)))
.values().stream()
.sorted(comparing(SortedSet::first))
.flatMap(Collection::stream)
.collect(toList());
Before Java 8
Edit: Here is a really rough unit test that demonstrates one way to do it. I haven't cleaned it up as much as i would have liked.
Stuff like this is painful in Java, and i would normally use Google Guava for this.
import org.junit.Test;
import java.util.*;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
public class GroupSortTest {
#Test
public void testGroupSort() {
List<Record> records = asList(
new Record("a", 3),
new Record("a", 9),
new Record("b", 7),
new Record("b", 10),
new Record("c", 8),
new Record("c", 3));
List<SortedMap<Integer, Record>> recordsGroupedByName = groupRecordsByNameAndSortedByScoreDescending(records);
Collections.sort(recordsGroupedByName, byHighestScoreInGroupDescending());
List<Record> result = flattenGroups(recordsGroupedByName);
List<Record> expected = asList(
new Record("b", 10),
new Record("b", 7),
new Record("a", 9),
new Record("a", 3),
new Record("c", 8),
new Record("c", 3));
assertEquals(expected, result);
}
private List<Record> flattenGroups(List<SortedMap<Integer, Record>> recordGroups) {
List<Record> result = new ArrayList<Record>();
for (SortedMap<Integer, Record> group : recordGroups) {
result.addAll(group.values());
}
return result;
}
private List<SortedMap<Integer, Record>> groupRecordsByNameAndSortedByScoreDescending(List<Record> records) {
Map<String, SortedMap<Integer, Record>> groupsByName = new HashMap<String, SortedMap<Integer, Record>>();
for (Record record : records) {
SortedMap<Integer, Record> group = groupsByName.get(record.getName());
if (null == group) {
group = new TreeMap<Integer, Record>(descending());
groupsByName.put(record.getName(), group);
}
group.put(record.getScore(), record);
}
return new ArrayList<SortedMap<Integer, Record>>(groupsByName.values());
}
private DescendingSortComparator descending() {
return new DescendingSortComparator();
}
private ByFirstKeyDescending byHighestScoreInGroupDescending() {
return new ByFirstKeyDescending();
}
private static class ByFirstKeyDescending implements Comparator<SortedMap<Integer, Record>> {
public int compare(SortedMap<Integer, Record> o1, SortedMap<Integer, Record> o2) {
return o2.firstKey().compareTo(o1.firstKey());
}
}
private static class DescendingSortComparator implements Comparator<Comparable> {
public int compare(Comparable o1, Comparable o2) {
return o2.compareTo(o1);
}
}
}
Foreach over the collection, and put the objects into a Map<String, SortedSet<YourObject>>, keyed by name, where the SortedSet is a TreeSet with a custom comparator that compares by score.
Then foreach over the map's values() collection, and put the groups into a SortedSet<SortedSet<YourObject>>, with a second custom comparator that compares SortedSets according to their largest element. Actually, instead of foreaching, you can simply use addAll().
Here's the code:
public class SortThings {
static class Thing {
public final String name;
public final int score;
public Thing(String name, int score) {
this.name = name;
this.score = score;
}
#Override
public String toString() {
return "(" + name + ", " + score + ")";
}
}
public static void main(String[] args) {
Collection<Thing> things = Arrays.asList(
new Thing("a", 3),
new Thing("a", 9),
new Thing("b", 7),
new Thing("b", 10),
new Thing("c", 8),
new Thing("c", 3)
);
SortedSet<SortedSet<Thing>> sortedGroups = sortThings(things);
System.out.println(sortedGroups);
}
private static SortedSet<SortedSet<Thing>> sortThings(Collection<Thing> things) {
final Comparator<Thing> compareThings = new Comparator<Thing>() {
public int compare(Thing a, Thing b) {
Integer aScore = a.score;
Integer bScore = b.score;
return aScore.compareTo(bScore);
}
};
// first pass
Map<String, SortedSet<Thing>> groups = new HashMap<String, SortedSet<Thing>>();
for (Thing obj: things) {
SortedSet<Thing> group = groups.get(obj.name);
if (group == null) {
group = new TreeSet<Thing>(compareThings);
groups.put(obj.name, group);
}
group.add(obj);
}
// second pass
SortedSet<SortedSet<Thing>> sortedGroups = new TreeSet<SortedSet<Thing>>(new Comparator<SortedSet<Thing>>() {
public int compare(SortedSet<Thing> a, SortedSet<Thing> b) {
return compareThings.compare(a.last(), b.last());
}
});
sortedGroups.addAll(groups.values());
return sortedGroups;
}
}
Note that the output is in smallest-to-largest order. That's the natural order with Java's collections; it would be trivial to modify this to sort the other way if that's what you need.
public class ScoreComparator implements Comparator<Item>
{
public int compare(Item a, Item b){
if (a.name.equals(b.name){
return a.score.compareTo(b.score);
}
return a.name.compareTo(b.Name);
}
}
I think you can do this. First check to see if the group is equal. If it is then compare on score. Otherwise return which group you want to be more on top. Let me code it up.
class Item{
String name;
int score;
}
new Comparator<Item>(){
#Override
public int compare(Item o1, Item o2) {
if (o1.name.equals(o2.name)) {
return o1.score > o2.score ? 1 : -1; // might have to flip this. I didn't test
}else {
return o1.name.compareTo(o2.name);
}
}
};
Yes Go for Comparator
Give first preference to name in comparison and then to score. it will be grouped up with sorted score also
List<Score> scores = new ArrayList<Score>();
scores.add(new Score("a", 58));
scores.add(new Score("a", 10));
scores.add(new Score("b", 165));
scores.add(new Score("a", 1));
scores.add(new Score("b", 1658));
scores.add(new Score("c", 1));
scores.add(new Score("c", 10));
scores.add(new Score("c", 0));
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
if (o1.getName().compareTo(o2.getName()) == 0) {
return o2.getScore() - o1.getScore();
} else {
return o1.getName().compareTo(o2.getName());
}
}
});
System.out.println(scores);
Update
As Chris pointed out.
import java.util.*;
/**
*
* #author Jigar
*/
class Score {
private String name;
private List<Integer> scores;
public Score() {
}
public Score(String name, List<Integer> scores) {
this.name = name;
this.scores = scores;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Integer> getScores() {
return scores;
}
public void setScores(List<Integer> scores) {
this.scores = scores;
}
#Override
public String toString() {
return name + " , " + scores + "\n";
}
}
public class ScoreDemo {
public static void main(String[] args) {
List<Score> scores = new ArrayList<Score>();
List<Integer> lstA = new ArrayList<Integer>();
lstA.add(3);
lstA.add(9);
lstA.add(7);
Collections.sort(lstA);
Collections.reverse(lstA);
List<Integer> lstB = new ArrayList<Integer>();
lstB.add(10);
lstB.add(8);
lstB.add(3);
Collections.sort(lstB);
Collections.reverse(lstB);
List<Integer> lstC = new ArrayList<Integer>();
lstC.add(8);
lstC.add(3);
Collections.sort(lstC);
Collections.reverse(lstC);
scores.add(new Score("a", lstA));
scores.add(new Score("b", lstB));
scores.add(new Score("c", lstC));
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
System.out.println(scores);
}
}
Here is working ideone demo
UPDATE: Here is working ideone demo

Categories