4

この問題にどのようなタイトルを付ければよいか、よくわかりません。これはJavaのわずかな手のように見えますが、Guava Collections2.transformを使用してのみ発生しています。トランスフォーマーは、「結果」の反復中にオブジェクトの完全に異なるインスタンスを提供し、「結果」が最終的に返されるときに含まれるものを提供しています。したがって、「setDateStamp()」は、幽霊のように現れては消えるように見えるインスタンスに設定されているため、実際には機能していないように見えます。

Collections2.transform() メソッドと論理的に同等の機能 (コードをコメントアウト) を実装すると、期待どおりの結果が得られます。私はGoogleコード、ブレークポイント、およびすべてをステップ実行しましたが、基礎となる関数以外のメソッドを介して作成された新しいインスタンスはどこにもありません.

私は彼らの実装が何をしているかを理解しています:必要に応じて変換します。複雑ではありません。では、なぜこれが機能しないのでしょうか。

ここに問題のコードといくつかのデバッグがあります

@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}]
4

2 に答える 2

9

新しいオブジェクトへの書き込みがバッキングコレクションに書き込まれていないことに驚いていますか?

Collections.transform「必要に応じて」変換を実行するだけでなく、何も保存しません それが、ドキュメントでの「ビュー」の意味です。Collections2.transformedコレクションをウォークスルーするたびに、関数が新たに適用されます。メソッドのforループapplyがで行われるとresult、そのオブジェクトはなくなります。二度と見られない。

自分がしていることを実行したい場合は、変換されたコレクションの明示的なコピーをたとえばで作成しArrayListます。

于 2012-05-17T07:15:25.750 に答える
3

答えはjavadocにありますが、簡単な答えは変換が怠惰であるということです。返されるのは古いコレクションのビューであり、要素にアクセスするたびに関数が呼び出されます。これは、それらのいくつかにしかアクセスしない場合に便利です。何度か繰り返すことがわかっている場合は、ビューを新しいコレクションにコピーすることをお勧めします。

于 2012-05-17T07:16:11.203 に答える