使用比较器,如何确定对象之间的匹配质量,或者有更好的方法

时间:2018-08-13 12:53:50

标签: java comparator

我有一个代码库,试图确定所提供服务之间的相似性。这些服务具有类别。但是,我想通过比较类别集,服务时间和服务成本来确定相似度。我已经编写了代码,并且可以按预期工作(我认为),但是我感觉到我缺少一些东西,因此我想将其放在此处以获取一些反馈并获得一些理解。

测试

@Test
public void testSimilarProjectComparatorSorting() {
    List<ProjectService> projectServices = createProjectServices();

    System.out.println(projectServices);

    projectServices.sort(new SimilarProjectComparator());

    System.out.println(projectServices);

    // Assertions
}

public static List<ProjectService> createProjectServices() {
    List<ProjectService> projectServices = new ArrayList<>();

    ProjectService projectService = new ProjectService();
    projectService.setAmount(new BigDecimal(1800));
    projectService.setDifficultyScale(Estimation.FIVE);

    Category genericCat = new Category();
    genericCat.setName("Generic");
    genericCat.setSlug("generic");

    Category listingCat = new Category();
    listingCat.setName("Listing");
    listingCat.setSlug("listing");

    Category webCat = new Category();
    webCat.setName("Web");
    webCat.setSlug("web");

    projectService.setCategories(new HashSet<>(Arrays.asList(genericCat, listingCat, webCat)));

    projectServices.add(projectService);

    projectService = new ProjectService();
    projectService.setAmount(new BigDecimal(800));
    projectService.setDifficultyScale(Estimation.THREE);

    Category outliningCat = new Category();
    outliningCat.setName("Outlining");
    outliningCat.setSlug("outlining");

    Category bullHeadedCat = new Category();
    bullHeadedCat.setName("Bull-Headed");
    bullHeadedCat.setSlug("bull-headed");

    projectService.setCategories(
            new HashSet<>(
                    Arrays.asList(
                            outliningCat,
                            bullHeadedCat,
                            webCat
                    )
            )
    );

    projectServices.add(projectService);

    projectService = new ProjectService();
    projectService.setAmount(new BigDecimal(1500));
    projectService.setDifficultyScale(Estimation.FIVE);

    Category writingCat = new Category();
    writingCat.setName("Writing");
    writingCat.setSlug("writing");

    projectService.setCategories(
            new HashSet<>(
                    Arrays.asList(
                            writingCat,
                            genericCat,
                            listingCat
                    )
            )
    );

    projectServices.add(projectService);

    projectService = new ProjectService();
    projectService.setAmount(new BigDecimal(1400));
    projectService.setDifficultyScale(Estimation.TWO);

    projectService.setCategories(
            new HashSet<>(
                    Arrays.asList(
                            writingCat,
                            genericCat,
                            listingCat,
                            webCat
                    )
            )
    );

    projectServices.add(projectService);

    return projectServices;
}

代码

public class SimilarProjectComparator implements Comparator<ProjectService> {
    @Override
    public int compare(ProjectService o1, ProjectService o2) {
        Set<Category> o1CategorySet = o1.getCategories();
        Set<Category> o2CategorySet = o2.getCategories();
        Integer categoryMatch = 0;
        Double matchQuality = 0.0;

        if (o1CategorySet != null && o2CategorySet != null) {
            for (Category o1Category : o1CategorySet) {
                for (Category o2Category : o2CategorySet) {
                    Integer match = o1Category.getName().compareTo(o2Category.getName());
                    if (match > 0) {
                        categoryMatch++;
                    } else {
                        categoryMatch--;
                    }
                }
            }
        }

        if (categoryMatch > 0) {
            matchQuality++;
        } else {
            matchQuality--;
        }

        Integer scaleMatch = o1.getDifficultyScale().getEstimation().compareTo(
                o2.getDifficultyScale().getEstimation()
        );

        if (scaleMatch > 0) {
            matchQuality++;
        } else {
            matchQuality--;
        }

        Integer amountMatch = o1.getAmount().compareTo(o2.getAmount());

        if (amountMatch > 0) {
            matchQuality++;
        } else {
            matchQuality--;
        }

        return matchQuality.intValue();
    }
}

我会假设顺序是(根据类别的相似程度来判断):1400、1500、800,然后是1800。但是,实际的顺序是:800、1400、1500、1800。而且不确定我是否做对了。 我是否缺少某些东西,或者它是否可以正常工作,这是我的假设是不正确的?我了解到我正在尝试使用3种不同的道具来确定对象匹配的质量,因此如何相似这些类别并不能保证我上面提到的顺序,除非它具有更大的分量。从业务逻辑的角度来看,我认为这不是必需的。我只是比较者的新手,并试图理解这一点。感谢您提前提供的帮助!

1 个答案:

答案 0 :(得分:1)

您正在寻找相似之处。如果比较两个元素的结果为0,则这些元素相同。否则他们不是。我将您的例行更改为:

public int compare(ProjectService o1, ProjectService o2) {
    Set<Category> o1CategorySet = o1.getCategories();
    Set<Category> o2CategorySet = o2.getCategories();
    int categoryMatch = 0;
    double matchQuality = 0.0;

    if ((o1CategorySet != null) && (o2CategorySet != null)) {
        for (Category o1Category : o1CategorySet) {
            for (Category o2Category : o2CategorySet) {
                int match = o1Category.getName().compareTo(o2Category.getName());
                if (match == 0) {
                    categoryMatch++;
                } else {
                    categoryMatch--;
                }
            }
        }
    }

    if (categoryMatch == 0) {
        matchQuality++;
    } else {
        matchQuality--;
    }

    int scaleMatch = o1.getDifficultyScale().getEstimation().compareTo(o2.getDifficultyScale().getEstimation());

    if (scaleMatch == 0) {
        matchQuality++;
    } else {
        matchQuality--;
    }

    int amountMatch = o1.getAmount().compareTo(o2.getAmount());

    if (amountMatch == 0) {
        matchQuality++;
    } else {
        matchQuality--;
    }

    return (int) matchQuality;
}

排序应该可以正常工作。