diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/infrastructure/item/support/MappingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/infrastructure/item/support/MappingItemWriter.java
new file mode 100644
index 0000000000..0d035f83ce
--- /dev/null
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/infrastructure/item/support/MappingItemWriter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.infrastructure.item.support;
+
+import org.springframework.batch.infrastructure.item.Chunk;
+import org.springframework.batch.infrastructure.item.ItemWriter;
+
+import java.util.function.Function;
+
+/**
+ * Adapts an {@link ItemWriter} accepting items of type {@link U} to one accepting items
+ * of type {@link T} by applying a mapping function to each item before writing.
+ *
+ * The {@code MappingItemWriter} is most useful when used in combination with a
+ * {@link org.springframework.batch.infrastructure.item.support.CompositeItemWriter},
+ * where the mapping function in front of the downstream writer can be a getter of the
+ * input item or a more complex transformation logic.
+ *
+ * This adapter mimics the behavior of
+ * {@link java.util.stream.Collectors#mapping(Function, java.util.stream.Collector)}.
+ *
+ * @param the type of the input items
+ * @param type of items accepted by downstream item writer
+ * @author Stefano Cordio
+ * @since 6.0
+ */
+public class MappingItemWriter implements ItemWriter {
+
+ private final Function super T, ? extends U> mapper;
+
+ private final ItemWriter super U> downstream;
+
+ /**
+ * Create a new {@link MappingItemWriter}.
+ * @param mapper the mapping function to apply to the input items
+ * @param downstream the downstream item writer that accepts mapped items
+ */
+ public MappingItemWriter(Function super T, ? extends U> mapper, ItemWriter super U> downstream) {
+ this.mapper = mapper;
+ this.downstream = downstream;
+ }
+
+ @Override
+ public void write(Chunk extends T> chunk) throws Exception {
+ downstream.write(new Chunk<>(chunk.getItems().stream().map(mapper).toList()));
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterIntegrationTests.java
new file mode 100644
index 0000000000..4e637de183
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterIntegrationTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.infrastructure.item.support;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.batch.infrastructure.item.Chunk;
+import org.springframework.batch.infrastructure.item.ItemWriter;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Stefano Cordio
+ */
+class MappingItemWriterIntegrationTests {
+
+ @Test
+ void testWithCompositeItemWriter() throws Exception {
+ // given
+ record Person(String name, int age) {
+ }
+
+ ListItemWriter nameItemWriter = new ListItemWriter<>();
+ ListItemWriter ageItemWriter = new ListItemWriter<>();
+
+ ItemWriter underTest = new CompositeItemWriter<>(List.of( //
+ new MappingItemWriter<>(Person::name, nameItemWriter), //
+ new MappingItemWriter<>(Person::age, ageItemWriter)));
+
+ // when
+ underTest.write(Chunk.of(new Person("Foo", 42), new Person("Bar", 24)));
+ underTest.write(Chunk.of(new Person("Baz", 21), new Person("Qux", 12)));
+
+ // then
+ assertThat(nameItemWriter.getWrittenItems()).containsExactly("Foo", "Bar", "Baz", "Qux");
+ assertThat(ageItemWriter.getWrittenItems()).containsExactly(42, 24, 21, 12);
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterTests.java
new file mode 100644
index 0000000000..ee85a221c1
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/infrastructure/item/support/MappingItemWriterTests.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.infrastructure.item.support;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.batch.infrastructure.item.Chunk;
+
+import java.util.function.Function;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+/**
+ * @author Stefano Cordio
+ */
+class MappingItemWriterTests {
+
+ @Test
+ void testWithMapperAcceptingItemSuperclass() throws Exception {
+ // given
+ Function mapper = Entity::name;
+ ListItemWriter downstream = mock();
+ MappingItemWriter underTest = new MappingItemWriter<>(mapper, downstream);
+
+ // when
+ underTest.write(Chunk.of(new Person("Foo", 42)));
+
+ // then
+ verify(downstream).write(Chunk.of("Foo"));
+ }
+
+ @Test
+ void testWithMapperProducingMappedItemSubclass() throws Exception {
+ // given
+ Function mapper = Person::name;
+ ListItemWriter downstream = mock();
+ MappingItemWriter underTest = new MappingItemWriter<>(mapper, downstream);
+
+ // when
+ underTest.write(Chunk.of(new Person("Foo", 42)));
+
+ // then
+ verify(downstream).write(Chunk.of("Foo"));
+ }
+
+ @Test
+ void testWithDownstreamAcceptingMappedItemSuperclass() throws Exception {
+ // given
+ Function mapper = Person::name;
+ ListItemWriter downstream = mock();
+ MappingItemWriter underTest = new MappingItemWriter<>(mapper, downstream);
+
+ // when
+ underTest.write(Chunk.of(new Person("Foo", 42)));
+
+ // then
+ verify(downstream).write(Chunk.of("Foo"));
+ }
+
+ private interface Entity {
+
+ String name();
+
+ }
+
+ private record Person(String name, int age) implements Entity {
+ }
+
+}