collect () полезно, когда у вас есть возможные альтернативные представления ваших объектов.
Например, недавно я имел дело с фрагментом кода, который должен был соответствовать спискам объектов из двух разных источников. Эти объекты были разных классов, так как они использовались в разных точках кода, но для моих целей имели одни и те же соответствующие понятия (т.е. у них обоих был идентификатор, у обоих был путь свойства, у обоих был флаг «каскад» и т. Д.) .
Я обнаружил, что гораздо проще определить простое промежуточное представление этих свойств (как внутренний класс), определить преобразователи для обоих классов конкретных объектов (опять же, очень просто, поскольку для вывода свойств используются только соответствующие методы доступа) и затем используйте collect()
, чтобы преобразовать мои входящие объекты в промежуточное представление. Как только они появятся, я смогу использовать стандартные методы коллекций для сравнения и манипулирования двумя наборами.
Итак, в качестве (полу) конкретного примера, скажем, мне нужен метод для проверки того, что набор объектов на уровне представления является подмножеством объектов, кэшированных на уровне данных. С подходом, изложенным выше, это будет сделано примерно так:
public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
final List<IntermediateRepresentation> presObjects = CollectionUtils.collect(pres.getObjects(), PRES_TRANSFORMER);
final List<IntermediateRepresentation> dataObjects = CollectionUtils.collect(dataSpec.getCached(), DATA_TRANSFORMER);
return dataObjects.containsAll(presObjects);
}
Для меня это гораздо более читабельно, поскольку последняя строка передает реальный смысл того, что метод делает , чем эквивалент с циклами:
public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
for (PresSpecificObject presObj : pres.getObjects())
{
boolean matched = false;
for (CachedDataObject dataObj : dataSpec.getCached())
{
if (areObjectsEquivalent(presObj, dataObj)) // or do the tests inline but a method is cleaner
{
matched = true;
break;
}
}
if (matched == false)
{
return false;
}
}
// Every column must have matched
return true;
}
Эти два, вероятно, примерно так же эффективны, но с точки зрения читабельности я бы сказал, что первый намного легче понять сразу. Несмотря на то, что в целом получается больше строк кода (из-за определения внутреннего класса и двух преобразователей), отделение реализации обхода от действительной логики «истина или ложь» делает последнюю намного понятнее. Плюс, если у вас есть какие-либо метрики KLOC, они тоже не могут быть бусинками. ; -)