Тема: Map. Capped Map. Допоможіть зрозуміти чому падають тести
Добрий вечір. Прошу вашої допомоги з цим завданням. Використовую IntelliJ IDEA.
Int String Capped Map
The purpose of this exercise is to train you in implementing Collections.Estimated workload of this exercise is 180 min.
Description
Please, proceed to IntStringCappedMap and implement its methods.IntStringCappedMap is a Map with Integer keys and String values.
"Capped" means that this map has a capacity property.
Total length of all String values in a map must not exceed its capacity.
If a new added value would lead to such overflowing, the map must evict its current entries until adding new value would not exceed its capacity.
Eviction must follow the order of adding values to the map - the oldest value must be evicted first.
Note that if length of the new String value is more than capacity, map must throw an IllegalArgumentException and evict no entry.You need to implement following methods:
entrySet - the method is partially implemented.
It returns an AbstractSet and you must only provide implementations for its iterator next and hasNext methods.
get - return a value by its key.
put - set a value by a given key.
If it leads to exceeding capacity, be sure to evict as many of the oldest elements as needed.
remove - removes a value by key.
size - returns number of map entries.
Example
IntStringCappedMap map = new IntStringCappedMap(25);
map.put(5, "Five");
map.put(6, "Six");
map.put(7, "Seven");
map.put(8, "Eight");
map.put(12, "Twelve");
map.put(9, "Nine");
map.put(1, "One");System.out.println(new TreeMap<>(map));
//{1=One, 7=Seven, 8=Eight, 9=Nine, 12=Twelve}
Ось моя реалізація. Наведений в завданні приклад виконується.
import java.util.*;
class IntStringCappedMap extends AbstractMap<Integer, String> {
private final long capacity;
private final Map<Integer, String> map;
public IntStringCappedMap(final long capacity) {
this.capacity = capacity;
map = new LinkedHashMap<>((int)capacity);
}
public long getCapacity() {
return capacity;
}
@Override
public Set<Entry<Integer, String>> entrySet() {
return new AbstractSet<>() {
@Override
public Iterator<Entry<Integer, String>> iterator() {
return new Iterator<>() {
Set<Entry<Integer, String>> entry = map.entrySet();
Iterator iterator = entry.iterator();
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<Integer, String> next() {
return (Entry<Integer, String>) iterator.next();
}
};
}
@Override
public int size() {
return IntStringCappedMap.this.size();
}
};
}
@Override
public String get(final Object key) {
return map.get(key);
}
@Override
public String put(final Integer key, final String value) {
if (value.length() > capacity) throw new IllegalArgumentException();
while (totalSizeOfValues() + value.length() > capacity) {
// так я видаляю найстаріший елемент, тобто пару яка потрапила перша
for (Map.Entry<Integer, String> entry : map.entrySet()) {
map.remove(entry.getKey());
break;
}
}
return map.put(key, value);
}
@Override
public String remove(final Object key) {
return map.remove(key);
}
@Override
public int size() {
return map.size();
}
private long totalSizeOfValues() {
long total_size = 0;
for (Map.Entry<Integer, String> entry: map.entrySet()) {
total_size += entry.getValue().length();
}
return total_size;
}
}
Але тест не проходить. Ось частина повідомлення.
Expected :map(20):[3:3333333, 4:99999, 6:00, 7:2, 8:7, 9:0]
Actual :map(20):[3:3333333, 4:99999, 6:00, 7:2, 9:0]
Ось тест
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.company.autotasks.collections.IntStringCappedMapTest.toStringSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.params.provider.Arguments.arguments;
class IntStringCappedMapRandomTest {
static Stream<Arguments> testCases() {
return Stream.of(
42,
654692,
7714,
845632,
15966,
12358,
852139,
8569,
112584,
3263
).map(i -> arguments(i, expectedList(i)));
}
@ParameterizedTest(name = "[{index}] {0}")
@MethodSource("testCases")
void testInitialState(int seed, List<String> expected) {
Random random = new Random(seed);
IntStringCappedMap map = new IntStringCappedMap(10 + random.nextInt(20));
Iterator<String> expectedIt = expected.iterator();
int iterations = 10 + random.nextInt(10);
for (int i = 0; i < iterations; i++) {
if (random.nextInt(4) != 0) {
map.put(random.nextInt(10),
Integer.toString(random.nextInt(10))
.repeat(random.nextInt(8))
);
} else {
map.remove(random.nextInt(5));
}
assertEquals(expectedIt.next(), toString(map));
}
}
private String toString(final IntStringCappedMap map) {
return "map(" + map.getCapacity() + "):" + toStringSet(map).toString();
}
private void writeFile(final int seed, final String actual) {
try {
Files.writeString(
Path.of("src", "test", "resources", seed + ".txt"),
actual + "\n", StandardOpenOption.APPEND, StandardOpenOption.CREATE);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static List<String> expectedList(int seed) {
try {
return Files.readAllLines(Path.of("src", "test", "resources", seed + ".txt"));
} catch (IOException e) {
return List.of();
}
}
}
Будь ласка, виділіть свій час, щоб допомогти мені.
І відразу ж хочу подякувати за те, що прочитали до цього рядка.