将Java int[]数组转换为HashSet<Integer>

59
我有一个整数数组:
int[] a = {1, 2, 3};

我需要一个类型化的集合:

Set<Integer> s;

如果我执行以下操作:

s = new HashSet(Arrays.asList(a));

当然,它认为我的意思是:

List<int[]>

而我想说的是:

List<Integer>

这是因为int是一个原始类型。 如果我使用了String,那么所有的都会起作用:

Set<String> s = new HashSet<String>(
    Arrays.asList(new String[] { "1", "2", "3" }));

如何轻松、正确而简洁地实现以下转换:

A) int[] a...
B) Integer[] a ...

谢谢!


1
可能是重复的问题:https://dev59.com/P3NA5IYBdhLWcg3wI6V4 - David B
8个回答

74

使用流:

// int[] nums = {1,2,3,4,5}
Set<Integer> set = Arrays.stream(nums).boxed().collect(Collectors.toSet())

25

这个问题实际上包含两个独立的部分:将 int[] 转换为 Integer[]和使用 int[] 创建一个 HashSet<Integer>。在Java 8中,这两个操作都可以用流(streams)轻松完成:

int[] array = ...
Integer[] boxedArray = IntStream.of(array).boxed().toArray(Integer[]::new);
Set<Integer> set = IntStream.of(array).boxed().collect(Collectors.toSet());
//or if you need a HashSet specifically
HashSet<Integer> hashset = IntStream.of(array).boxed()
    .collect(Collectors.toCollection(HashSet::new));

我认为值得一提的是,这种行技巧速度较慢。我使用了 IntStream.of(nums).boxed().collect(Collectors.toSet()) 而不是仅循环遍历元素,这使我的运行时间从平均18ms增加到25ms。 - Janac Meena

10

进一步解释。asList方法具有以下签名

public static <T> List<T> asList(T... a)

所以如果你这样做:

List<Integer> list = Arrays.asList(1, 2, 3, 4)

或者这样:

List<Integer> list = Arrays.asList(new Integer[] { 1, 2, 3, 4 })
在这些情况下,我相信Java能够推断出您想要一个List集合返回,因此它会填充类型参数,并期望在方法调用中使用Integer类型的参数。由于它可以将int值自动装箱为Integer对象,所以这是可以接受的。
然而,这种情况不起作用。
List<Integer> list = Arrays.asList(new int[] { 1, 2, 3, 4} )

因为原始类型到包装器类型的转换(例如 int[] 到 Integer[])不是内置于语言中的(不确定为什么他们没有这样做,但他们没有)。

因此,每种原始类型都必须被处理为它自己的重载方法,这就是 commons 包所做的。例如:

public static List<Integer> asList(int i...);

我相信你也可以调用 Arrays.<Integer>asList(1, 2, 3, 4) - ILMTitan
24
问题的标题是 Java int[] array to HashSet<Integer>,但你的答案中没有提到 HashSet - NobleUplift

4

或者你可以轻松使用Guavaint[]转换为List<Integer>

Ints.asList(int...)

asList

public static List<Integer> asList(int... backingArray)

返回由指定数组支持的固定大小列表,类似于Arrays.asList(Object[])。该列表支持List.set(int, Object),但任何试图将值设置为null的尝试都将导致NullPointerException

返回的列表维护了写入或从中读取的Integer对象的值,但不维护其身份。例如,对于返回的列表,list.get(0) == list.get(0)是否为真是未指定的。


2

您可以在Apache Commons中使用ArrayUtils:

int[] intArray  = { 1, 2, 3 };
Integer[] integerArray = ArrayUtils.toObject(intArray);

1
如果Commons有一个方法来做这件事,那就意味着使用基本的JDK没有办法做到...感谢指引! - Robottinosino
Commons库在Android上占用了大量的方法引用,强烈建议避免使用它。这在普通Java中是有道理的,并且运行良好。 - milosmns
Apache Commons的链接无法使用.....如何使用ArrayUtils? - Anjan Biswas

1

另一种选择是使用Eclipse Collections的原始集合。您可以轻松将int[]转换为MutableIntSet,然后转换为Set<Integer>Integer[],如下所示,或者直接使用MutableIntSet,这样会更节省内存并且性能更好。

int[] a = {1, 2, 3};
MutableIntSet intSet = IntSets.mutable.with(a);
Set<Integer> integerSet = intSet.collect(i -> i);  // auto-boxing
Integer[] integerArray = integerSet.toArray(new Integer[]{});

如果您想直接从int数组转换为Integer数组并保留顺序,则这样做可以实现。
Integer[] integers = 
        IntLists.mutable.with(a).collect(i -> i).toArray(new Integer[]{});

注意:我是 Eclipse Collections 的提交者。

0
只需使用以下代码片段,将数组中的元素添加到Set中即可。
public class RemoveDuplicateElements {

    public static void main(String args[]){
        int array[] =  {0,1,2,3,4,5,6,7,8,9,1,2,3,4,5};
        Set <Integer> abc = new HashSet <Integer>();
        for (Integer t:array){  
            abc.add(t); 
        }       
        System.out.println("sampleSet"+abc);  
    }

}

OP正在询问JAVA8的方法。 - Zohra Khan

-1
不需要循环:
只需将数组转换为列表
然后将此列表转换为哈希集。
例如:
List list = Arrays.asList(your_array);
Set set = new HashSet<>(list);
这对我来说非常完美。

1
你的回答可以通过添加更多支持性信息来改进。请[编辑]以添加进一步的细节,例如引用或文档,以便他人可以确认您的回答是正确的。您可以在帮助中心中找到有关如何编写好答案的更多信息。 - Community
这段代码不起作用。 - Anjan Biswas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接