Java 8 – 按照 Map 的键和值对列表进行排序

huangapple go评论76阅读模式
英文:

Java 8 - Sort a List by Map's Key and Value

问题

End goal is to sort the list for the following scenario: 

I have an enum with the BLOCKER being the highest severity an MINOR being the lowest.

public enum Severity {
    MINOR(0)
    MAJOR(1),
    BLOCKER(2);

I have a class SeverityProfile

public class SeverityProfile {

    private final Map<Severity, Integer> severities;

    public SeverityProfile(Map<Severity, Integer> severities) {
        this.severities = Collections.unmodifiableMap(severities);
    }

    public Map<Severity, Integer> getSeverities() {
        return severities;
    }

The main object AggregatedData


public class AggregatedData {

 
    private final SeverityProfile severityProfile;
    ... other private variables

    public AggregatedData(SeverityProfile severityProfile) {

        this.severityProfile = severityProfile;
  
    }


    public SeverityProfile getSeverityProfile() {
        return severityProfile;
    }
    ... other getters
}

Now, I have to sort the List<AggregatedData> aggregatedData by the Severity of the map.
aggregatedData.get(0).getSeverityProfile().getSeverities() has BLOCKER - 1 and MAJOR - 2
aggregatedData.get(1).getSeverityProfile().getSeverities() has BLOCKER - 3 and MAJOR - 2 and MINOR - 4
aggregatedData.get(2).getSeverityProfile().getSeverities() has MAJOR - 2 and MINOR - 8
aggregatedData.get(3).getSeverityProfile().getSeverities() has MAJOR - 5 and MINOR - 10

If I want the descending values, then the result should be:

  • aggregatedData.get(1) - BLOCKER - 3 and MAJOR - 2 and MINOR - 4
  • aggregatedData.get(0) - BLOCKER - 1 and MAJOR - 2
  • aggregatedData.get(3) - MAJOR - 5 and MINOR - 10
  • aggregatedData.get(2) - MAJOR - 2 and MINOR - 8

(Notice MAJOR which is next priority to BLOCKER has higher count in get(3) than get(2))

I'd like to do a Collections.sort(aggregatedData, new Comparator<AggregatedData>() {

Problem is, I have to compare the Severity and also the values associated with it.
I'm not sure how to construct the Comparator in this case.


<details>
<summary>英文:</summary>

End goal is to sort the list for the following scenario: 

I have an enum with the BLOCKER being the highest severity an MINOR being the lowest.

public enum Severity {
MINOR(0)
MAJOR(1),
BLOCKER(2);


I have a class SeverityProfile

public class SeverityProfile {

private final Map&lt;Severity, Integer&gt; severities;

public SeverityProfile(Map&lt;Severity, Integer&gt; severities) {
    this.severities = Collections.unmodifiableMap(severities);
}

public Map&lt;Severity, Integer&gt; getSeverities() {
    return severities;
}

The main object AggregatedData

public class AggregatedData {

private final SeverityProfile severityProfile;
... other private variables

public AggregatedData(SeverityProfile severityProfile) {

    this.severityProfile = severityProfile;

}


public SeverityProfile getSeverityProfile() {
    return severityProfile;
}
... other getters

}


Now, I have to sort the  ```List&lt;AggregatedData&gt; aggregatedData``` by the Severity of the map.
```aggregatedData.get(0).getSeverityProfile().getSeverities()``` has BLOCKER - 1 and MAJOR - 2
```aggregatedData.get(1).getSeverityProfile().getSeverities()``` has BLOCKER - 3 and MAJOR - 2 and MINOR - 4
```aggregatedData.get(2).getSeverityProfile().getSeverities()``` has MAJOR - 2 and MINOR - 8
```aggregatedData.get(3).getSeverityProfile().getSeverities()``` has MAJOR - 5 and MINOR - 10

If I want the descending values, then the result should be:

 - ```aggregatedData.get(1)``` - BLOCKER - 3 and MAJOR - 2 and MINOR - 4
 - ```aggregatedData.get(0)``` - BLOCKER - 1 and MAJOR - 2
 - ```aggregatedData.get(3)``` - MAJOR - 5 and MINOR - 10
 - ```aggregatedData.get(2)``` - MAJOR - 2 and MINOR - 8 

(Notice MAJOR which is next priority to BLOCKER has higher count in get(3) than get(2))


I&#39;d like to do a  ```Collections.sort(aggregatedData, new Comparator&lt;AggregatedData&gt;() { ```

Problem is, I have to compare the ```Severity``` and also the values associated with it. 
I&#39;m not sure how to construct the Comparator in this case.



</details>


# 答案1
**得分**: 0

回答我的问题:

```java
public class SeverityProfile implements Comparable<SeverityProfile> {

    private final Map<Severity, Integer> severities;

    private final int[] counts;

    public SeverityProfile(Map<Severity, Integer> severities) {
        counts = new int[Severity.values().length];

        this.severities = Collections.unmodifiableMap(severities);

        counts[Severity.BLOCKER.ordinal()] = severities.getOrDefault(Severity.BLOCKER, 0);
        counts[Severity.MAJOR.ordinal()] = severities.getOrDefault(Severity.MAJOR, 0);
        counts[Severity.MINOR.ordinal()] = severities.getOrDefault(Severity.MINOR, 0);
    }

    public Map<Severity, Integer> getSeverities() {
        return severities;
    }

    public int[] getCounts() {
        return counts;
    }

    @Override
    public int compareTo(SeverityProfile other) {
        if (other == this) {
            return 0;
        }

        for (Severity severity : Severity.getSeveritiesByDescendingRank()) {
            if (getCounts()[severity.ordinal()] != other.getCounts()[severity.ordinal()]) {
                return getCounts()[severity.ordinal()] - other.getCounts()[severity.ordinal()];
            }
        }
        return 0;
    }
}

我在 Collections.sort 中使用了比较器(Comparator),并使用了上述的 compareTo 方法。

英文:

Answering my own question:

public class SeverityProfile implements Comparable&lt;SeverityProfile&gt; {

    private final Map&lt;Severity, Integer&gt; severities;

    private final int[] counts;

    public SeverityProfile(Map&lt;Severity, Integer&gt; severities) {
        counts = new int[Severity.values().length];

        this.severities = Collections.unmodifiableMap(severities);

        counts[Severity.BLOCKER.ordinal()] = severities.getOrDefault(Severity.BLOCKER, 0);
        counts[Severity.MAJOR.ordinal()] = severities.getOrDefault(Severity.MAJOR, 0);
        counts[Severity.MINOR.ordinal()] = severities.getOrDefault(Severity.MINOR, 0);
    }


    public Map&lt;Severity, Integer&gt; getSeverities() {
        return severities;
    }

    public int[] getCounts() {
        return counts;
    }

    @Override
    public int compareTo(SeverityProfile other) {
        if (other == this) {
            return 0;
        }

        for (Severity severity : Severity.getSeveritiesByDescendingRank()) {
            if (getCounts()[severity.ordinal()] != other.getCounts()[severity.ordinal()]) {
                return getCounts()[severity.ordinal()] - other.getCounts()[severity.ordinal()];

            }
        }
        return 0;
    }
}

I used Comparator in the Collections.sort and used the above compareTo method.

huangapple
  • 本文由 发表于 2020年9月25日 22:53:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/64066535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定