使用Google Guava Collections2.transform的怪异

Chr*_*rno 4 java mockito guava

我并不完全确定能够解决这个问题的标题是什么.这看起来像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;
    }
}
Run Code Online (Sandbox Code Playgroud)

下一堂课

@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;
}
Run Code Online (Sandbox Code Playgroud)

}

并且测试

@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}]
Run Code Online (Sandbox Code Playgroud)

Lou*_*man 9

你对新对象的写入没有写入后备集合感到惊讶吗?

Collections.transform不只是"根据需要"进行转换 - 它根本不存储任何东西. 这就是"视图"在其文档中的含义.每当您浏览Collections2.transformed集合时,它都会再次应用该功能.一旦apply完成了方法中的for循环result,该对象就消失了; 从未见过.

如果你想做你正在做的事情,请在例如a中制作变换后的集合的明确副本ArrayList.