Добавить уникальное ограничение или индекс:
create unique index unq_table_col on table(col);
РЕДАКТИРОВАТЬ: Этот ответ основан на идее, что вам нужно сделать аналогичные вещи для разных объектов и разных свойств в другом месте в вашем коде. Если вам только нужно преобразовать список ViewValues в список Long по идентификатору, то придерживайтесь своего исходного кода. Однако, если вам нужно более многократно используемое решение, читайте дальше ...
Я бы объявил интерфейс для проекции, например
public interface Function<Arg,Result>
{
public Result apply(Arg arg);
}
Затем вы можете написать один общий метод преобразования:
public <Source, Result> List<Result> convertAll(List<Source> source,
Function<Source, Result> projection)
{
ArrayList<Result> results = new ArrayList<Result>();
for (Source element : source)
{
results.add(projection.apply(element));
}
return results;
}
Затем вы можете определить простые проекции. как это:
private static final Function<ViewValue, Long> ID_PROJECTION =
new Function<ViewValue, Long>()
{
public Long apply(ViewValue x)
{
return x.getId();
}
};
И применить это так:
List<Long> ids = convertAll(values, ID_PROJECTION);
(Очевидно, что использование K & R-связываний и более длинных линий делает объявление проекции немного короче:)
Честно говоря, все это будет намного лучше с лямбда-выражениями, но не бери в голову ...
Я реализовал небольшую функциональную библиотеку для этого варианта использования. Один из методов имеет такую сигнатуру:
<T> List<T> mapToProperty(List<?> objectList, String property, Class<T> returnType)
Которая принимает строку и использует отражение для создания вызова свойства, затем возвращает список, поддерживаемый objectList, где get и итератор реализованы с использованием этого вызова свойства.
Функции mapToProperty реализованы в терминах общей функции карты, которая принимает функцию в качестве преобразователя, как описано в другом посте. Очень полезно.
Я предлагаю вам ознакомиться с базовым функциональным программированием и, в частности, взглянуть на Функторы (объекты, реализующие функцию карты)
Изменить: Отражение действительно не должно быть дорогостоящим. JVM значительно улучшилась в этой области. Просто убедитесь, что вы скомпилировали вызов один раз и использовали его повторно.
Edit2: Пример кода
public class MapExample {
public static interface Function<A,R>
{
public R apply(A b);
}
public static <A,R> Function<A,R> compilePropertyMapper(Class<A> objectType, String property, Class<R> propertyType)
{
try {
final Method m = objectType.getMethod("get" + property.substring(0,1).toUpperCase() + property.substring(1));
if(!propertyType.isAssignableFrom(m.getReturnType()))
throw new IllegalArgumentException(
"Property "+property+" on class "+objectType.getSimpleName()+" is not a "+propertyType.getSimpleName()
);
return new Function<A,R>()
{
@SuppressWarnings("unchecked")
public R apply(A b)
{
try {
return (R)m.invoke(b);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
};
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T1,T2> List<T2> map(final List<T1> list, final Function<T1,T2> mapper)
{
return new AbstractList<T2>()
{
@Override
public T2 get(int index) {
return mapper.apply(list.get(index));
}
@Override
public int size() {
return list.size();
}
};
}
@SuppressWarnings("unchecked")
public static <T1,T2> List<T2> mapToProperty(List<T1> list, String property, Class<T2> propertyType)
{
if(list == null)
return null;
else if(list.isEmpty())
return Collections.emptyList();
return map(list,compilePropertyMapper((Class<T1>)list.get(0).getClass(), property, propertyType));
}
}
Вы можете использовать оболочку:
public class IdList impements List<Long>
{
private List<ViewValue> underlying;
pubic IdList(List<ViewValue> underying)
{
this.underlying = underying;
}
public Long get(int index)
{
return underlying.get(index).getId()
}
// other List methods
}
, хотя это еще более утомительная работа, она может улучшить производительность.
Вы также можете реализовать свое и мое решение в общем, используя рефлексию, но это очень плохо для перфорации.
Я боюсь, нет короткого и простого универсального решения в Java. В Groovy вы бы просто использовали collect (), но я считаю, что это также подразумевает рефлексию.
Это зависит от того, что вы затем делаете с List
и List
Например, вы можете получить достаточную функциональность, создав собственную реализацию List, которая обертывает список List
, реализуя iterator ()
с реализацией итератора, которая перебирает ViewValues, возвращая идентификатор.
Вы можете сделать это в однострочном режиме, используя Commons BeanUtils и Collections:
(зачем писать свой собственный код, когда другие сделали это за вас?)
import org.apache.commons.beanutils.BeanToPropertyValueTransformer;
import org.apache.commons.collections.CollectionUtils;
...
List<Long> ids = (List<Long>) CollectionUtils.collect(viewValues,
new BeanToPropertyValueTransformer("id"));