Не очень хороший способ сделать это. Наивный подход был бы к
- Проверьте, что это список / набор / коллекция
- Проверьте все элементы
Entry
s - Проверьте все ключи и значения из каждого
Entry
являются String
s
Например,
Map<String, String> map = new HashMap<>();
map.put("a", "b");
Object entries = map.entrySet();
boolean safe = Optional.of(entries)
.filter(Set.class::isInstance)
.map(e -> (Set<?>) e)
.filter(set -> set.stream().allMatch(Map.Entry.class::isInstance))
.map(e -> (Set<Map.Entry<?, ?>>) e)
.filter(set -> set.stream().allMatch(e -> e.getKey() instanceof String && e.getValue() instanceof String))
.isPresent();
Однако даже это не дает достаточной уверенности. Предположим, что карта была объявлена как:
Map<String, Object> map = new HashMap<>();
map.put("a", "b");
Во время нашей проверки это будет считаться безопасным. Это набор, и все записи в настоящее время являются строками. Однако, если какой-то другой код позже будет мутировать карту, например,
map.add("b", 123);
, тогда вы поймете, что этот бросок все еще небезопасен. Вы можете работать только с текущим состоянием, поэтому вы не можете дать никаких гарантий относительно будущего состояния.
Вы можете обойти это несколькими способами:
- Глубокая копия всей коллекции после проверки. Но как насчет состояния гонки после проверки перед копированием? Вам придется использовать блокировку.
- Сделать карту неизменной
Как насчет того, если это коллекция, но в настоящее время она пуста? В этом случае вы не можете делать какие-либо проверки на предметах.
Как видите, работа с таким составом - очень тяжелая работа, и во многих местах вы можете потенциально go ошибиться. Лучше всего избегать таких бросков.