Я хотел бы преобразовать массив в набор в Java. Есть несколько очевидных способов сделать это (то есть с помощью цикла), но я хотел бы что-то более аккуратное, что-то вроде:
java.util.Arrays.asList(Object[] a);
Любые идеи?
Я хотел бы преобразовать массив в набор в Java. Есть несколько очевидных способов сделать это (то есть с помощью цикла), но я хотел бы что-то более аккуратное, что-то вроде:
java.util.Arrays.asList(Object[] a);
Любые идеи?
Ответы:
Нравится:
Set<T> mySet = new HashSet<>(Arrays.asList(someArray));
В Java 9+, если немодифицируемый набор в порядке:
Set<T> mySet = Set.of(someArray);
В Java 10+ параметр общего типа может быть выведен из типа компонента массивов:
var mySet = Set.of(someArray);
Arrays.asListявляется O (1).
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);
Это Collections.addAll (java.util.Collection, T ...) из JDK 6.
Дополнительно: что если наш массив полон примитивов?
Для JDK <8, я бы просто написал очевидный forцикл, чтобы сделать перенос и добавление-набор за один проход.
Для JDK> = 8 привлекательный вариант выглядит примерно так:
Arrays.stream(intArray).boxed().collect(Collectors.toSet());
java.util.Collections.addAll. Кроме того, я бы больше не рекомендовал Commons Collections, поскольку он не генерируется и Guava не существует.
addAllбудет O ( N ).
С Guava вы можете сделать:
T[] array = ...
Set<T> set = Sets.newHashSet(array);
new HashSet<T>(Arrays.asList(someArray)). См. Google.github.io/guava/releases/19.0/api/docs/com/google/common/…
Java 8:
String[] strArray = {"eins", "zwei", "drei", "vier"};
Set<String> strSet = Arrays.stream(strArray).collect(Collectors.toSet());
System.out.println(strSet);
// [eins, vier, zwei, drei]
У нас также есть возможность использования Stream. Мы можем получить поток различными способами:
Set<String> set = Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));
System.out.println(set);
String[] stringArray = {"A", "B", "C", "D"};
Set<String> strSet1 = Arrays.stream(stringArray).collect(Collectors.toSet());
System.out.println(strSet1);
// if you need HashSet then use below option.
Set<String> strSet2 = Arrays.stream(stringArray).collect(Collectors.toCollection(HashSet::new));
System.out.println(strSet2);
Исходный код Collectors.toSet()показывает, что элементы добавляются один за другим, HashSetно спецификация не гарантирует, что это будет HashSet.
«Нет никаких гарантий относительно типа, изменчивости, сериализуемости или безопасности потоков возвращаемого набора».
Так что лучше использовать более поздний вариант. Выход:
[A, B, C, D]
[A, B, C, D]
[A, B, C, D]
Java 9 представил Set.ofстатический метод фабрики, который возвращает неизменный набор для предоставленных элементов или массива.
@SafeVarargs
static <E> Set<E> of(E... elements)
Проверьте непреложный Набор статических фабричные методы для деталей.
Мы также можем получить неизменный набор двумя способами:
Set.copyOf(Arrays.asList(array))Arrays.stream(array).collect(Collectors.toUnmodifiableList());Метод Collectors.toUnmodifiableList()внутренне использует Set.ofвведенный в Java 9. Также проверьте мой ответ для большего.
Stream.of()- я этого не знал. Небольшое возражение Collectors.toSet(): вы говорите, что спецификация не гарантирует добавление элементов один за другим, но именно это означает: «накапливается ... в новом Set». И это более читабельно - на мой взгляд, предпочтительнее, если вам не нужны гарантии конкретного типа, изменчивости, сериализуемости и безопасности потоков.
HashSet. Это только гарантирует, что это будет, Setи это то, что я имею в виду. Надеюсь, я прояснил это.
После того как Arrays.asList(array)вы можете выполнитьSet set = new HashSet(list);
Вот пример метода, который вы можете написать:
public <T> Set<T> GetSetFromArray(T[] array) {
return new HashSet<T>(Arrays.asList(array));
}
В Eclipse Collections будет работать следующее:
Set<Integer> set1 = Sets.mutable.of(1, 2, 3, 4, 5);
Set<Integer> set2 = Sets.mutable.of(new Integer[]{1, 2, 3, 4, 5});
MutableSet<Integer> mutableSet = Sets.mutable.of(1, 2, 3, 4, 5);
ImmutableSet<Integer> immutableSet = Sets.immutable.of(1, 2, 3, 4, 5);
Set<Integer> unmodifiableSet = Sets.mutable.of(1, 2, 3, 4, 5).asUnmodifiable();
Set<Integer> synchronizedSet = Sets.mutable.of(1, 2, 3, 4, 5).asSynchronized();
ImmutableSet<Integer> immutableSet = Sets.mutable.of(1, 2, 3, 4, 5).toImmutable();
Примечание: я являюсь коммиттером для коллекций Eclipse
Быстро: вы можете сделать:
// Fixed-size list
List list = Arrays.asList(array);
// Growable list
list = new LinkedList(Arrays.asList(array));
// Duplicate elements are discarded
Set set = new HashSet(Arrays.asList(array));
и повернуть вспять
// Create an array containing the elements in a list
Object[] objectArray = list.toArray();
MyClass[] array = (MyClass[])list.toArray(new MyClass[list.size()]);
// Create an array containing the elements in a set
objectArray = set.toArray();
array = (MyClass[])set.toArray(new MyClass[set.size()]);
Я написал ниже из совета выше - укради это ... это приятно!
/**
* Handy conversion to set
*/
public class SetUtil {
/**
* Convert some items to a set
* @param items items
* @param <T> works on any type
* @return a hash set of the input items
*/
public static <T> Set<T> asSet(T ... items) {
return Stream.of(items).collect(Collectors.toSet());
}
}
Там было много хороших ответов уже, но большинство из них не будет работать с массивом примитивов (например int[], long[], char[],byte[] и т.д.)
В Java 8 и выше, вы можете связать массив с:
Integer[] boxedArr = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Затем преобразуйте в набор, используя поток:
Stream.of(boxedArr).collect(Collectors.toSet());
Иногда помогает использование некоторых стандартных библиотек. Попробуйте взглянуть на коллекции Apache Commons . В этом случае ваши проблемы просто трансформируются в нечто подобное
String[] keys = {"blah", "blahblah"}
Set<String> myEmptySet = new HashSet<String>();
CollectionUtils.addAll(pythonKeywordSet, keys);
java.util.Collections.addAll(myEmptySet, keys);??
Использовать CollectionUtilsили ArrayUtilsизstanford-postagger-3.0.jar
import static edu.stanford.nlp.util.ArrayUtils.asSet;
or
import static edu.stanford.nlp.util.CollectionUtils.asSet;
...
String [] array = {"1", "q"};
Set<String> trackIds = asSet(array);
В Java 10 :
String[] strs = {"A", "B"};
Set<String> set = Set.copyOf(Arrays.asList(strs));
Set.copyOfвозвращает неизменяемое, Setсодержащее элементы данного Collection.
Данное Collectionне должно быть null, и оно не должно содержать каких - либо nullэлементов.
private Map<Integer, Set<Integer>> nobreaks = new HashMap();
nobreaks.put(1, new HashSet(Arrays.asList(new int[]{2, 4, 5})));
System.out.println("expected size is 3: " +nobreaks.get(1).size());
выход
expected size is 3: 1
изменить на
nobreaks.put(1, new HashSet(Arrays.asList( 2, 4, 5 )));
выход
expected size is 3: 3
Для тех, кто решает для Android:
Звездочка *является spreadоператором. Он применяет все элементы в коллекции по отдельности, каждый из которых передается в порядке varargпараметра метода. Это эквивалентно:
val myArray = arrayOf("data", "foo")
val mySet = setOf(*myArray)
// Equivalent to
val mySet = setOf("data", "foo")
// Multiple spreads ["data", "foo", "bar", "data", "foo"]
val mySet = setOf(*myArray, "bar", *myArray)
Передача без параметров setOf() приводит к пустому набору.
В дополнение к этому setOfвы также можете использовать любой из них для определенного типа хеша:
hashSetOf()
linkedSetOf()
mutableSetOf()
sortableSetOf()
Вот как явно определить тип элемента коллекции.
setOf<String>()
hashSetOf<MyClass>()
new HashSet<Object>(Arrays.asList(Object[] a));
Но я думаю, что это будет более эффективным:
final Set s = new HashSet<Object>();
for (Object o : a) { s.add(o); }
HashSetзадается на основе размера массива.
Set<T> b = new HashSet<>(Arrays.asList(requiredArray));