В других словах
document.querySelector()
выбирает только первый элемент указанного селектора. Поэтому он не выплевывает массив, это одно значение. Подобно document.getElementById()
, который извлекает только ID-элементы, поскольку идентификаторы должны быть уникальными. document.querySelectorAll()
выбирает все элементы с указанным селектором и возвращает их в массиве. Похоже на document.getElementsByClassName()
только для классов и document.getElementsByTagName()
.
Зачем использовать querySelector?
Используется просто для единственной цели легкость и краткость.
Зачем использовать getElement / sBy? *
Более быстрая производительность.
Почему это различие в производительности?
Оба способа выбора имеют целью создание NodeList для дальнейшего использования. querySelectors генерирует статический NodeList с селекторами, поэтому он должен быть сначала создан с нуля. getElement / sBy * немедленно адаптирует существующий живой NodeList текущего DOM.
Итак, когда использовать какой метод зависит от вас / вашего проекта / вашего устройства.
Infos
Демонстрация всех методов Документация NodeList Тест производительности
EDIT: этот ответ основан на идее, что вам нужно будет делать подобные вещи для разных объектов и разных свойств в другом месте вашего кода. Если вы только должны преобразовать список ViewValues в список Longs by ID, тогда придерживайтесь своего исходного кода. Однако, если вы хотите использовать более многоразовое решение, прочитайте ...
Я бы объявил интерфейс для проекции, например
public interface Function<Arg,Result>
{
public Result apply(Arg arg);
}
. Тогда вы можете написать одно общее преобразование method:
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 & amp; R и более длинных строк упрощает объявление прокрутки:)
Честно говоря, все это было бы намного лучше с лямбда-выражениями, но неважно ...
Мы можем сделать это в одной строке кода, используя java 8
List<Long> ids = viewValues.stream().map(ViewValue::getId).collect(Collectors.toList());
. Для получения дополнительной информации: Java 8 - Потоки
Я реализовал небольшую функциональную библиотеку для этой утилиты. Один из методов имеет эту подпись:
<T> List<T> mapToProperty(List<?> objectList, String property, Class<T> returnType)
Что берет строку и использует отражение для создания вызова свойства, а затем возвращает список, поддерживаемый objectList, где get и iterator реализованы с использованием этого вызова свойства .
Функции 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
}
, хотя это еще более утомительная работа, это может повысить производительность.
Вы также можете реализовать свое и мое решение с помощью отражения, но это будет очень плохо для успеха.
Theres не краткое и простое универсальное решение на Java, я боюсь. В Groovy вы просто используете collect (), но я считаю, что это также связано с отражением.
Используйте коллекцию google. Пример:
Function<ViewValue, Long> transform = new Function<ViewValue, Long>() {
@Override
public Long apply(ViewValue from) {
return from.getId();
}
};
List<ViewValue> list = Lists.newArrayList();
List<Long> idsList = Lists.transform(list, transform);
UPDATE:
На Java 8 вам не нужен Guava. Вы можете:
import com.example.ViewValue;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
Function<ViewValue, Long> transform = ViewValue::getId;
List<ViewValue> source = new ArrayList<>();
List<Long> result = source.stream().map(transform).collect(Collectors.toList());
Или просто:
List<ViewValue> source= new ArrayList<>();
List<Long> result = source.stream().map(ViewValue::getId).collect(Collectors.toList());
СЛЕДУЮЩЕЕ ОБНОВЛЕНИЕ (последнее после изменения Javaslang на Vavr):
В настоящее время это стоит упомянуть о решении с библиотекой Javaslang ( http://www.javaslang.io/ ) библиотека Vavr ( http://www.vavr.io/ ). Предположим, что у нас есть наш список с подлинными объектами:
List<ViewValue> source = newArrayList(new ViewValue(1), new ViewValue(2), new ViewValue(2));
Мы могли бы сделать преобразование с помощью класса List из библиотеки Javaslang (в конечном счете сбор не удобен):
List<Long> result = io.vavr.collection.List.ofAll(source).map(ViewValue::getId).toJavaList();
Но вы увидите власть только с списками Javaslang:
io.vavr.collection.List<ViewValue> source = javaslang.collection.List.of(new ViewValue(1), new ViewValue(2), new ViewValue(3));
io.vavr.collection.List<Long> res = source.map(ViewValue::getId);
Я рекомендую посмотреть доступные коллекции и новые типы в этой библиотеке (особенно мне нравится тип Try). Вы найдете документацию по следующему адресу: http://www.javaslang.io/javaslang-docs/ http://www.vavr.io/vavr-docs/ .
PS. Из-за Oracle и слова «Java» в названии им пришлось изменить имя библиотеки из javaslang на что-то еще. Они решили Вавра.
Это зависит от того, что вы делаете с List<Long>
и List<ViewValue>
. Например, вы можете получить достаточную функциональность от создания собственной реализации списка, которая обертывает List<ViewValue>
, реализуя 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"));
viewValue.id
было переименовано, код все равно будет компилироваться, но сбой во время выполнения.
– Steve Chambers
8 November 2016 в 11:30