[英]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.