簡體   English   中英

Hamcrest Matcher在字符串列表中沒有重復項?

[英]Hamcrest Matcher for no duplicates in a List of Strings?

我想要一個簡單的hamcrest匹配器來查找List<String>對象的重復項。 這就是我寫的

for (QuizEntity quiz : quizzes)
            for (QuestionEntity question : quiz.getQuestions())
                Assert.assertThat("There should be no duplicate questions", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));

不幸的是我得到了這個輸出,這不夠描述。 任何

java.lang.AssertionError: There should be no duplicate questions
Expected: <20>
     but: was <1>

實際上有一個實現的方法就是這樣做 - doesNotHaveDuplicates

 Assertions.assertThat(list).doesNotHaveDuplicates();

您可以使用Java 8進行測驗並將其映射到問題,並斷言沒有重復

另一種選擇是使用來自Cirneco庫的 hasDistinctElements()匹配器(最后是Hamcrest擴展)。

它可以使用如下:

Assert.assertThat("There should be no duplicate questions", questions, CirnecoMatchersJ7.hasDistinctElements());

雖然我建議這樣做

import static CirnecoMatchersJ7.*;

使其更具人性化

assertThat("There should be no duplicate questions", questions, hasDistinctElements());

Cirneco也有一些流利的代表,即

given(questions).withReason("There should be no duplicate questions").assertThat(hasDistinctElements());

可以按如下方式導入依賴項:

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>java7-hamcrest-matchers</artifactId>
  <version>0.7.0</version>
</dependency>

更換

Assert.assertThat("There should be no duplicate questions", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));

Assert.assertThat("Question '" + question.getQuestion() + "' should not be duplicated", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));

我為此實現了自己的匹配器。 請注意錯誤消息對我不正常(顯示另一個條目而不是重復條目)。 我與社區分享代碼(如果您想在產品中使用,請鏈接和upvote)

編碼

public static class DistinctMatcher<T> extends BaseMatcher<T>
{
    private final Set<T> theSet = new HashSet<>();

    public static <T> Matcher<? super T> distinct()
    {
        return new DistinctMatcher<T>();
    }

    @Override
    public void describeTo(Description description)
    {
        description.appendText("has distinct values");
    }

    @Override
    public void describeMismatch(Object item, Description description)
    {
        description.appendText("element found twice: ").appendValue(item);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean matches(Object arg0)
    {
        return theSet.add((T) arg0);
    }

}

這個怎么運作

通過維護有狀態的HashSet ,匹配器被實例化一次並由迭代的每個項目饋送。 根據Set.add方法,它告訴您該集合是否包含該項目,因此匹配是立即的。

用法:(我在非嵌套集合上測試過它)

assertThat(quizzes,(everyItem(hasProperty("questions",everyItem(hasProperty("question",is(distinct())))))));

性能考慮因素

上面的匹配器不適用於無約束的惰性集合(例如迭代器超過數十億條記錄),因為Set擁有對象的永久引用。 可以輕松修改匹配器以僅擁有對象的hashCode ,但應記住內存要求。

任何其他基於集合的解決方案都會遇到同樣的問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM