简体   繁体   English

Java使用启示比较器对列表进行排序

[英]Java sort a list with revelance comparator

I'm trying to sort a list of music by revelance corresponding to a list of criteria. 我正在尝试根据与条件列表相对应的启示对音乐列表进行排序。

public class Music implements Comparable<CriteriaList> {
    private String genre, artist, album, titre, price, note; 
    // getters, setters
    public int compareTo(CriteriaList list) {
        boolean title, album, genre, artist, note;
        title = !list.getTitle().isEmpty() && this.getTitre().equals(list.getTitle());
        album = !list.getAlbum().isEmpty() && this.getAlbum().equals(list.getAlbum());
        genre = !list.getGenre().isEmpty() && this.getGenre().equals(list.getGenre());
        artist = !list.getArtist().isEmpty() && this.getArtist().equals(list.getArtist());
        note = !list.getNote().isEmpty() && (Integer.parseInt(this.getNote()) >= Integer.parseInt(list.getNote()));
        return ((title ? 1 : 0) + (album ? 1 : 0) + (genre ? 1 : 0) + (artist ? 1 : 0) + (note ? 1 : 0));
    }
}

My function compareTo return the number of fields which match to the criteria list and test if input are not empty. 我的函数compareTo返回与条件列表匹配的字段数,并测试输入是否为空。

public class MusicProvider extends Agent {
    public List<Music> getMusicsByCL(CriteriaList list) {
        ArrayList<Music> res = new ArrayList<Music>();
        int[] revelanceTab = new int[res.size()];
        int i = 0, revelance;
        for (Music music : musicListAvailable) {
            revelance = music.compareTo(list);
            if (revelance > 1) {
                res.add(music);
                revelanceTab[++i] = revelance;
            }
        }
        // sort res with revelanceTab
        return res;
    }
}

Here I want to retrieve musics with a minimun revelance of 1 and sort them by revelance. 在这里,我要检索最小启示度为1的音乐,并按启示性对它们进行排序。 How can I do that ? 我怎样才能做到这一点 ?

Assuming you have already created the functionality to actually calculate the relevance, I would proceed like this. 假设您已经创建了实际计算相关性的功能,我将像这样继续进行。

Create a simple class to hold the Music and the calculated relevance score, just pass in the Criteria and store the result of the calculation. 创建一个简单的类来保存音乐和计算出的相关性分数,只需传递条件并存储计算结果即可。

public class ScoredMusic {
    private int relevanceScore;
    public ScoredMusic(Music m) { ... }
    public void calculateRelevance(Criteria criteria) { ... }
    public Music getMusic() { ... }
    public int getRelevanceScore() { ... }
}

Then I would score all the Music instances you have, store them in a list, and do a very simple compareTo() implementation that simply compares the relevanceScore between each ScoredMusic instance. 然后,我将比分你的所有音乐的情况下,将它们存储在一个列表中,并做了非常简单compareTo()实现了简单的比较relevanceScore每间ScoredMusic实例。

Comparable is used to compare two instances of Music against each other. Comparable用于比较Music的两个实例。 If you want to compare to an external entity, use a Comparator implementation and pass it to Collections.sort(List, Comparator) . 如果要与外部实体进行比较,请使用Comparator实现并将其传递给Collections.sort(List,Comparator) The Comparator would need to be initialized with the CriteriaList and the compare method would return a positive number if the first element should be ranked higher, negative number if the second element should be ranked higher, or 0 if they are equivalent. 比较器将需要使用CriteriaList进行初始化,如果第一个元素的排名较高,则compare方法将返回正数;如果第二个元素的排名较高,则compare方法将返回负数;如果等效,则返回0。 In your example, you would use your compareTo method and subtract the second element's score from the first and return that. 在您的示例中,您将使用compareTo方法并从第一个元素中减去第二个元素的分数,然后将其返回。

Something like this: 像这样:

import java.util.Comparator;

public class MusicComparator implements Comparator<Music> {

    private final CriteriaList criteria;

    public MusicComparator(CriteriaList criteria) {
        this.criteria = criteria;
    }
    @Override
    public int compare(Music o1, Music o2) {
        return score(o1) - score(o2);
    }

    private int score(Music music) {
        boolean title, album, genre, artist, note;
        title = criteria.getTitle().isEmpty() || criteria.getTitle().equals(music.getTitle());
        album = criteria.getAlbum().isEmpty() || criteria.getAlbum().equals(music.getAlbum());
        genre = criteria.getGenre().isEmpty() || criteria.getGenre().equals(music.getGenre());
        artist = criteria.getArtist().isEmpty() || criteria.getArtist().equals(music.getArtist());
        note = criteria.getNote().isEmpty() || (!music.getNote().isEmpty() && Integer.parseInt(music.getNote()) >= Integer.parseInt(criteria.getNote()));
        return ((title ? 1 : 0) + (album ? 1 : 0) + (genre ? 1 : 0) + (artist ? 1 : 0) + (note ? 1 : 0));
    }
}

By the way, the isEmpty() methods will not protect you from null pointer exceptions. 顺便说一句,isEmpty()方法不会保护您免受空指针异常的影响。 You will need a better method of handling those if the fields are allowed to be null. 如果允许字段为空,则将需要一种更好的方法来处理这些字段。

This is my final class, 这是我的最后一堂课

public class ScoredMusic implements Comparable<ScoredMusic> {
    private int revelanceScore = 0;
    private Music music;

    public ScoredMusic(Music music, CriteriaList crit) {
        this.music = music;
        calculateRevelance(crit);
    }

    private void calculateRevelance(CriteriaList list) {
        boolean title, album, genre, artist, note;
        title = !list.getTitle().isEmpty() && music.getTitre().equals(list.getTitle());
        album = !list.getAlbum().isEmpty() && music.getAlbum().equals(list.getAlbum());
        genre = !list.getGenre().isEmpty() && music.getGenre().equals(list.getGenre());
        artist = !list.getArtist().isEmpty() && music.getArtist().equals(list.getArtist());
        note = !list.getNote().isEmpty() && (Integer.parseInt(music.getNote()) >= Integer.parseInt(list.getNote()));
        revelanceScore = ((title ? 1 : 0) + (album ? 1 : 0) + (genre ? 1 : 0) + (artist ? 1 : 0) + (note ? 1 : 0));
    }

    public Music getMusic() {
        return music;
    }

    public int getRevelanceScore() {
        return revelanceScore;
    }

    public int compareTo(ScoredMusic other) {
        return Integer.compare(this.getRevelanceScore(), other.getRevelanceScore());
    }
}

and in my second class 在我的第二堂课

public List<ScoredMusic> getMusicsScoredByCL(CriteriaList list) {
    ArrayList<ScoredMusic> scoredMusics = new ArrayList<ScoredMusic>();
    ScoredMusic sc;
    for (Music music : musicListAvailable) {
        sc = new ScoredMusic(music, list);
        scoredMusics.add(sc);
    }
    // sort by revelance and descending order
    Collections.sort(scoredMusics, Collections.reverseOrder());
    return scoredMusics;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM