I am having the following data in my list:
List<FeatureAnalyzeDTOResult> list = new ArrayList<>();
list.add(new FeatureAnalyzeDTOResult("october", 46));
list.add(new FeatureAnalyzeDTOResult("april", 46));
list.add(new FeatureAnalyzeDTOResult("march", 46));
list.add(new FeatureAnalyzeDTOResult("november", 30));
list.add(new FeatureAnalyzeDTOResult("may", 46));
list.add(new FeatureAnalyzeDTOResult("january", 53));
list.add(new FeatureAnalyzeDTOResult("december", 30));
What am I trying to do?
I am trying to sort this data in a sequence such that the data is sorted by month and the month should start from the current month and count the previous six months.
For example:
Currently, it is May, and the data should be sorted in the following order:
[MAY, APRIL, MARCH, FEBRUARY, JANUARY, DECEMBER]
And if any month is missing, it should simply skip it and go for the next month and should complete the count.
What I have tried so far?
I have tried the following code to get the current month and the preceding six months:
YearMonth thisMonth = YearMonth.now();
String[] month = new String[6];
for (int i = 0; i < 6; i ) {
YearMonth lastMonth = thisMonth.minusMonths(i);
DateTimeFormatter monthYearFormatter = DateTimeFormatter.ofPattern("MMMM");
month[i] = lastMonth.format(monthYearFormatter);
month[i] = month[i].toUpperCase();
}
List<String> monthList = Arrays.asList(month);
System.out.println(monthList);
I have also tried writing a Comparator
but it is not working as expected. I am a bit confused with the logic to write the Comparator
.
Comparator<FeatureAnalyzeDTOResult> comp = (o1, o2)
-> monthList.indexOf(o2.getMonth().toUpperCase()) - monthList.indexOf(o1.getMonth().toUpperCase());
list.sort(comp);
It gives the output as follows:
[Feature: december Count: 30
, Feature: january Count: 53
, Feature: march Count: 46
, Feature: april Count: 46
, Feature: may Count: 46
, Feature: october Count: 46
, Feature: november Count: 30]
Here is the FeatureAnalyzeDTOResult
class for reference:
class FeatureAnalyzeDTOResult {
private String month;
private int count;
public FeatureAnalyzeDTOResult(String feature, int count) {
this.month = feature;
this.count = count;
}
public FeatureAnalyzeDTOResult() {
}
public String getMonth() {
return month;
}
public void setMonth(String feature) {
this.month = feature;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("Feature: ").append(getMonth()).append(" Count: ").append(getCount()).append(" \n");
return string.toString();
}
CodePudding user response:
Assuming current month will get the integer 0 (or 11), then assign each month a consecutive int.
for example, May = 0, June = 1, .... january = 8...
then, sort your input array and from there, the problem is really easy
CodePudding user response:
Here an alternative approach:
- Get a list of months from
Month
enum from thejava.time
API - Rotate the list using
Collections.rotate
and current month value - Reverse the list using
Collections.reverse
- Create a comparator to compare months based on the index of above list
- Stream, sort and limit
Something like
import java.util.Collections;
import java.util.Comparator;
public static void main(String[] args) {
List<FeatureAnalyzeDTOResult> list = new ArrayList<>();
list.add(new FeatureAnalyzeDTOResult("october", 46));
list.add(new FeatureAnalyzeDTOResult("april", 46));
list.add(new FeatureAnalyzeDTOResult("march", 46));
list.add(new FeatureAnalyzeDTOResult("november", 30));
list.add(new FeatureAnalyzeDTOResult("may", 46));
list.add(new FeatureAnalyzeDTOResult("january", 53));
list.add(new FeatureAnalyzeDTOResult("december", 30));
List<Month> months = new ArrayList<>(Arrays.asList(Month.values()));
Collections.rotate(months, 12 - YearMonth.now().getMonthValue());
Collections.reverse(months);
Comparator<FeatureAnalyzeDTOResult> comp =
Comparator.comparingInt(f -> months.indexOf(Month.valueOf(f.getMonth().toUpperCase())));
list.stream().sorted(comp).limit(6).forEach(System.out::println);
}
CodePudding user response:
Here's how I would do it:
enum Month {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
}
public static void main(String[] args) {
List<String> data = Arrays.asList("october", "april", "march", "november", "may", "january", "december");
Month currentMonth = Month.MAY;
List<String> thisYear = data.stream()
.filter(a -> Month.valueOf(a.toUpperCase()).ordinal() <= currentMonth.ordinal())
.collect(Collectors.toList());
List<String> lastYear = data.stream()
.filter(a -> Month.valueOf(a.toUpperCase()).ordinal() > currentMonth.ordinal())
.collect(Collectors.toList());
Comparator<String> monthComparator = new Comparator<String>() {
@Override
public int compare(String a, String b) {
Month mA = Month.valueOf(a.toUpperCase());
Month mB = Month.valueOf(b.toUpperCase());
return mB.compareTo(mA);
}
};
thisYear.sort(monthComparator);
lastYear.sort(monthComparator);
thisYear.addAll(lastYear);
System.out.println(thisYear);
}
CodePudding user response:
You're nearly there. What you're missing are 2 things:
- You forgot to filter out months that are more than 6 months ago.
- You got the comparison reversed (so you're seeing things in ascending instead of descending order).
The following does both filtering and sorting:
Comparator<FeatureAnalyzeDTOResult> comp =
Comparator.comparingInt(o -> monthList.indexOf(o.getMonth().toUpperCase()));
list = list.stream()
.filter(o -> monthList.contains(o.getMonth().toUpperCase()))
.sorted(comp)
.toList();
System.out.println(list);
Output:
[Feature: may Count: 46
, Feature: april Count: 46
, Feature: march Count: 46
, Feature: january Count: 53
, Feature: december Count: 30
]