簡體   English   中英

使用Google Guava Collections2.transform的怪異

[英]Weirdness Using Google Guava Collections2.transform

我並不完全確定能夠解決這個問題的標題是什么。 這看起來像Java一樣,但它只是使用Guava Collections2.transform。 變換器在迭代“結果”期間提供完全不同的對象實例,然后在“結果”最終返回時包含的內容。 因此,'setDateStamp()'實際上看起來並不起作用,因為它被設置在似乎剛出現並像鬼一樣消失的實例上。

當我實現Collections2.transform()方法的邏輯等價物(注釋掉代碼)時,我得到了我期望的結果。 我已經介紹了谷歌代碼,斷點和所有內容,並且沒有通過除基礎函數之外的任何方法創建新實例的位置。

我得到了他們的實現正在做的事情:根據需要進行轉換。 不復雜。 那么為什么地獄不起作用呢?

這是有問題的代碼以及一些調試

@Component
public class SurveyResultToQuestionResults implements Function<SurveyResult, Collection<QuestionResult>> {

@Autowired
private QuestionResultDtoToDomain dtoToDomain;

@Override
public Collection<QuestionResult> apply(@Nullable SurveyResult input) {
    Collection<QuestionResult> results = new HashSet<QuestionResult>();
    if (input != null) {
           // substitute this
//            for (QuestionResultDto dto : input.getResults()) {
//                QuestionResult result = dtoToDomain.apply(dto);
//                results.add(result);
//            }
        // for this
        results = Collections2.transform(input.getResults(), dtoToDomain);
        for (QuestionResult result : results) {
            long time = input.getSurveyTime().getTime();
            Timestamp dateStamp = new Timestamp(time);
            result.setDateStamp(dateStamp);
        }

    }
    return results;
    }
}

下一堂課

@Component
public class QuestionResultDtoToDomain implements Function<QuestionResultDto, QuestionResult> {

@Override
public QuestionResult apply(@Nullable QuestionResultDto input) {
    QuestionResult result = null;
    if (input != null)
        result = new QuestionResult(input.getAnswerOriginId(),input.getAnswer(),input.getQuestionId());
    return result;
}

}

並且測試

@RunWith(MockitoJUnitRunner.class)
public class SurveyTransformerTest {

    @Spy
    private QuestionResultDtoToDomain dtoToDomain = new QuestionResultDtoToDomain();

    @InjectMocks
    private SurveyResultToQuestionResults surveyResultToQuestionResults = new SurveyResultToQuestionResults();        
    @Test
    public void testSurveyToQuestionResults() throws Exception {
        Set<QuestionResultDto> answers = new HashSet<QuestionResultDto>();
        answers.add(new QuestionResultDto(17L,"question 2 answer"));
        answers.add(new QuestionResultDto(18L,"question 3 answer"));
        answers.add(new QuestionResultDto(19L,"question 4 answer"));
        SurveyResult result = new SurveyResult(10L,16L,new Date(),answers);
        Collection<QuestionResult> qresults = surveyResultToQuestionResults.apply (result);
        System.out.println(qresults);       
        for (QuestionResult qresult : qresults) {
            assertNotNull(qresult.getDateStamp());
        }

    }
}


Debug:
Bad implementation
[QuestionResult{questionResultId=null, answer='question 4 answer', dateStamp=null}, QuestionResult{questionResultId=null, answer='question 2 answer', dateStamp=null}, QuestionResult{questionResultId=null, answer='question 3 answer', dateStamp=null}]

Good implementation:
[QuestionResult{questionResultId=null, answer='question 4 answer', dateStamp=2012-05-17 00:02:18.615}, QuestionResult{questionResultId=null, answer='question 3 answer', dateStamp=2012-05-17 00:02:18.615}, QuestionResult{questionResultId=null, answer='question 2 answer', dateStamp=2012-05-17 00:02:18.615}]

你對新對象的寫入沒有寫入后備集合感到驚訝嗎?

Collections.transform不僅僅根據需要進行轉換 - 它根本不存儲任何內容。 這就是“視圖”在其文檔中的含義。 每當您瀏覽Collections2.transform ed集合時,它都會再次應用該函數。 一旦使用result完成了apply方法中的for循環,該對象就消失了; 從未見過。

如果您想要做您正在做的事情,請在例如ArrayList轉換集合的顯式副本。

答案是在javadoc中,但快速的答案是變換是懶惰的。 返回的是舊集合的視圖,每次訪問元素時都會調用該函數; 如果您只訪問其中的一些,這將非常有用。 如果您知道要多次迭代,最好將視圖復制到一個全新的Collection中。

暫無
暫無

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

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