У меня есть строка, которая сообщает мне, какой атрибут я должен использовать для некоторой фильтрации. Как я могу использовать эту строку для фактического доступа к данным в объекте?
У меня есть метод, который возвращает список строк, говорящих мне, как фильтровать мой список объектов. Такие как:
String[] { "id=123", "name=foo" }
Итак, моя первая идея состояла в том, чтобы разделить строку на 2 части с помощью:
filterString.split(" = ") и используйте первую часть строки (например, «id») для идентификации фильтруемого атрибута.
Что касается фона JS, я бы сделал это так:
const attr = filterString.split('=')[0]; // grabs the "id" part from the string "id=123", for example
const filteredValue = filterString.split('=')[1]; // grabs the "123" part from the string "id=123", for example
items.filter(el => el[`${attr}`] === filteredValue) // returns an array with the items where the id == "123"
Как бы я мог сделать это с Java?
Что ты пытаешься сделать? Проверить сериализацию/десериализацию
Это очень динамично для Java. Если переменные el в вашем фрагменте JS являются Map в Java, то это возможно, поскольку attr будет сопоставляться с ключами, но если предполагается, что attr соответствует именам свойств класса, я вижу только отражение, которое нужно использовать , что я обычно не рекомендую, кроме как в крайнем случае.




Этот код должен работать:
//create the filter map
Map<String, String> expectedFieldValueMap = new HashMap<>();
for (String currentDataValue : input) {
String[] keyValue = currentDataValue.split(" = ");
String expectedField = keyValue[0];
String expectedValue = keyValue[1];
expectedFieldValueMap.put(expectedField, expectedValue);
}
Затем выполните итерацию по списку входных объектов (использовали класс Employee с полями id и name и подготовили список тестовых данных с несколькими объектами Employee, называемыми inputEmployeeList, которые итерируются) и посмотрите, проходят ли все фильтры, используя отражение, хотя и медленное, это один из способов:
for (Employee e : inputEmployeeList) {
try {
boolean filterPassed = true;
for (String expectedField : expectedFieldValueMap.keySet()) {
String expectedValue = expectedFieldValueMap.get(expectedField);
Field fieldData = e.getClass().getDeclaredField(expectedField);
fieldData.setAccessible(true);
if (!expectedValue.equals(fieldData.get(e))) {
filterPassed = false;
break;
}
}
if (filterPassed) {
System.out.println(e + " object passed the filter");
}
} catch (Exception any) {
any.printStackTrace();
// handle
}
}
Вам не хватает третьей строки примера: Как получить доступ к члену объекта по имени (и отфильтровать массив по его значению)?
Вопрос ОП в том, если я правильно понял, что должно заменить вашу строку sysout.
Вы можете использовать отражения для получения полей класса по динамическому имени.
@Test
void test() throws NoSuchFieldException, IllegalAccessException {
String[] filters = {"id=123", "name=foo"};
List<Item> list = newArrayList(new Item(123, "abc"), new Item(2, "foo"), new Item(123, "foo"));
Class<Item> itemClass = Item.class;
for (String filter : filters) {
String key = StringUtils.substringBefore(filter, " = ");
String value = StringUtils.substringAfter(filter, " = ");
Iterator<Item> iterator = list.iterator();
while (iterator.hasNext()) {
Item item = iterator.next();
Field field = itemClass.getDeclaredField(key);
field.setAccessible(true);
Object itemValue = field.get(item);
if (!value.equals(String.valueOf(itemValue))) {
iterator.remove();
}
}
}
assertEquals(1, list.size());
}
Но я согласен с комментарием от sp00m - это медленно и потенциально опасно.
Java — строго типизированный язык, поэтому определение
itemтеперь актуально. Другими словами, укажите класс, который вы собираетесь использовать для списка/массиваitems.