Skip to content

Commit bee0fed

Browse files
authored
add identity map (#45)
* add identity map * fix tests
1 parent 7cb8129 commit bee0fed

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package it.aboutbits.springboot.toolbox.util;
2+
3+
import it.aboutbits.springboot.toolbox.type.identity.EntityId;
4+
import it.aboutbits.springboot.toolbox.type.identity.Identified;
5+
import org.jspecify.annotations.NullMarked;
6+
import org.springframework.data.util.Streamable;
7+
8+
import java.util.Collection;
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
import java.util.function.Function;
12+
import java.util.stream.Collectors;
13+
import java.util.stream.Stream;
14+
15+
@NullMarked
16+
public class MapByIdentity<ID extends EntityId<?>, E extends Identified<ID>> extends HashMap<ID, E> {
17+
public MapByIdentity(int initialCapacity, float loadFactor) {
18+
super(initialCapacity, loadFactor);
19+
}
20+
21+
public MapByIdentity(int initialCapacity) {
22+
super(initialCapacity);
23+
}
24+
25+
public MapByIdentity() {
26+
super();
27+
}
28+
29+
public MapByIdentity(Map<? extends ID, ? extends E> m) {
30+
super(m);
31+
}
32+
33+
public static <ID extends EntityId<?>, E extends Identified<ID>> MapByIdentity<ID, E> of(Collection<? extends E> items) {
34+
var map = new MapByIdentity<ID, E>(items.size());
35+
items.forEach(item -> map.put(item.getId(), item));
36+
return map;
37+
}
38+
39+
public static <ID extends EntityId<?>, E extends Identified<ID>> MapByIdentity<ID, E> of(Stream<? extends E> items) {
40+
var collected = items.collect(Collectors.toMap(
41+
Identified::getId,
42+
Function.identity()
43+
));
44+
45+
return new MapByIdentity<>(collected);
46+
}
47+
48+
public static <ID extends EntityId<?>, E extends Identified<ID>> MapByIdentity<ID, E> of(Streamable<? extends E> items) {
49+
return of(items.toList());
50+
}
51+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package it.aboutbits.springboot.toolbox.util;
2+
3+
import it.aboutbits.springboot.toolbox.type.identity.EntityId;
4+
import it.aboutbits.springboot.toolbox.type.identity.Identified;
5+
import lombok.Getter;
6+
import org.jspecify.annotations.NullMarked;
7+
import org.junit.jupiter.api.Nested;
8+
import org.junit.jupiter.api.Test;
9+
import org.springframework.data.util.Streamable;
10+
11+
import java.util.List;
12+
import java.util.stream.Stream;
13+
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
16+
@NullMarked
17+
class MapByIdentityTest {
18+
@Nested
19+
class Of {
20+
@Test
21+
void collection() {
22+
// given
23+
var id1 = new TestEntity.ID(1L);
24+
var id2 = new TestEntity.ID(2L);
25+
26+
var entity1 = new TestEntity(id1);
27+
var entity2 = new TestEntity(id2);
28+
29+
var entities = List.of(entity1, entity2);
30+
31+
// when
32+
var result = MapByIdentity.of(entities);
33+
34+
// then
35+
assertThat(result).hasSize(2)
36+
.containsEntry(id1, entity1)
37+
.containsEntry(id2, entity2);
38+
}
39+
40+
@Test
41+
void stream() {
42+
// given
43+
var id1 = new TestEntity.ID(1L);
44+
var id2 = new TestEntity.ID(2L);
45+
46+
var entity1 = new TestEntity(id1);
47+
var entity2 = new TestEntity(id2);
48+
49+
var entityStream = Stream.of(entity1, entity2);
50+
51+
// when
52+
var result = MapByIdentity.of(entityStream);
53+
54+
// then
55+
assertThat(result).hasSize(2)
56+
.containsEntry(id1, entity1)
57+
.containsEntry(id2, entity2);
58+
}
59+
60+
@Test
61+
void streamable() {
62+
// given
63+
var id1 = new TestEntity.ID(1L);
64+
var id2 = new TestEntity.ID(2L);
65+
66+
var entity1 = new TestEntity(id1);
67+
var entity2 = new TestEntity(id2);
68+
69+
var streamable = Streamable.of(entity1, entity2);
70+
71+
// when
72+
var result = MapByIdentity.of(streamable);
73+
74+
// then
75+
assertThat(result).hasSize(2)
76+
.containsEntry(id1, entity1)
77+
.containsEntry(id2, entity2);
78+
}
79+
80+
@Test
81+
void emptyCollection() {
82+
// given
83+
var entities = List.<TestEntity>of();
84+
85+
// when
86+
var result = MapByIdentity.of(entities);
87+
88+
// then
89+
assertThat(result).isEmpty();
90+
}
91+
92+
@Test
93+
void emptyStream() {
94+
// given
95+
var emptyStream = Stream.<TestEntity>empty();
96+
97+
// when
98+
var result = MapByIdentity.of(emptyStream);
99+
100+
// then
101+
assertThat(result).isEmpty();
102+
}
103+
104+
@Test
105+
void emptyStreamable() {
106+
// given
107+
var emptyStreamable = Streamable.<TestEntity>empty();
108+
109+
// when
110+
var result = MapByIdentity.of(emptyStreamable);
111+
112+
// then
113+
assertThat(result).isEmpty();
114+
}
115+
}
116+
117+
@Getter
118+
private static class TestEntity implements Identified<TestEntity.ID> {
119+
private final ID id;
120+
121+
TestEntity(ID id) {
122+
this.id = id;
123+
}
124+
125+
public record ID(
126+
Long value
127+
) implements EntityId<Long>, Comparable<ID> {
128+
@Override
129+
public String toString() {
130+
return String.valueOf(value());
131+
}
132+
133+
@Override
134+
public int compareTo(ID other) {
135+
return Long.compare(this.value, other.value);
136+
}
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)