如何将 Java HashSet<Integer> 转换为原始 int 数组?

Posted

技术标签:

【中文标题】如何将 Java HashSet<Integer> 转换为原始 int 数组?【英文标题】:How can I convert a Java HashSet<Integer> to a primitive int array? 【发布时间】:2011-01-27 21:57:26 【问题描述】:

我有一个HashSet&lt;Integer&gt;,里面有一堆Integers。我想把它变成一个数组,但是调用

hashset.toArray();

返回一个Object[]。除了手动遍历每个元素之外,有没有更好的方法将其转换为 int 的数组?我想将数组传递给

void doSomething(int[] arr)

它不会接受 Object[] 数组,即使我尝试像

一样投射它
doSomething((int[]) hashSet.toArray());

【问题讨论】:

【参考方案1】:

Apache 的 ArrayUtils 有这个(它仍然迭代 behind the scenes):

doSomething(ArrayUtils.toPrimitive(hashset.toArray()));

他们总是检查此类事情的好地方。

【讨论】:

自动 +1 推荐 Apache Commons。 @skaffman 我推荐 Apache Commons Lang ...虽然不是针对这个特殊问题...但无论如何,请采取行动;) 实际上,它不会在幕后迭代——它会迭代两次。有一个不必要的Integer[] 会减慢从集合创建原始数组的过程。实际上,我认为选择使用Integer[] 作为toPrimitive(..) 的参数而不是Iterable&lt;Integer&gt; 有点笨拙,因为Arrays.asList(Integer[]) 的操作比collection.toArray() 快得多。因此,我不会自动 +1 推荐 apache commons :) sfussenegger,Apache Commons(我的意思是“它”)只迭代一次。没错,数组的创建需要迭代。 @sfussenegger 实际上,答案中写的代码会产生一个Object[],所以它甚至不起作用。您需要ArrayUtils.toPrimitive(hashset.toArray(new Integer[0])),使其成为应有的低效解决方案。【参考方案2】:

试试这个。 使用 java 8。

    Set<Integer> set = new HashSet<>();
    set.add(43);
    set.add(423);
    set.add(11);
    set.add(44);
    set.add(56);
    set.add(422);
    set.add(34);
    int[] arr = set.stream().mapToInt(Integer::intValue).toArray();

【讨论】:

【参考方案3】:

即使没有 Apache Utils,您也可以将 Set&lt;Integer&gt; 转换为 Integer[]

Set<Integer> myset = new HashSet<Integer>();
Integer[] array = myset.toArray(new Integer[0]);

但是,如果您需要 int[],则必须遍历该集合。

【讨论】:

【参考方案4】:

您可以使用 Java 8 流从任何 Collection&lt;Integer&gt;(包括 HashSet&lt;Integer&gt;)创建 int[]

int[] array = coll.stream().mapToInt(Number::intValue).toArray();

当然,该库仍在代表您遍历集合(或其他流源)。

除了简洁且没有外部库依赖之外,如果您要复制非常大的集合,流还可以让您并行处理。

【讨论】:

简洁一点:int[] array = coll.stream().mapToInt(x -> x).toArray()【参考方案5】:

您还可以使用 toArray() 方法的 toArray(T[] contents) 变体。创建一个与 HashSet 大小相同的空整数数组,然后将其传递给 toArray() 方法:

Integer[] myarray = new Integer[hashset.size()];
doSomething(hashset.toArray(myarray));

您必须更改doSomething() 函数以接受Integer[] 数组而不是int[]。如果这不可行,您可以将toArray 返回的值数组转换为int[]

【讨论】:

这将有助于提供您的编译错误,以便我知道我的代码有什么问题。 为什么不自己编译一下呢?一旦你看到编译错误,我就可以解释它发生的原因。【参考方案6】:

你可以只使用 Guava 的:

Ints.toArray(Collection<? extends Number> collection)

【讨论】:

【参考方案7】:
public int[] toInt(Set<Integer> set) 
  int[] a = new int[set.size()];
  int i = 0;
  for (Integer val : set) a[i++] = val;
  return a;

现在我为您编写了代码,它不再是那种手册了,是吗? ;)

【讨论】:

手动编写代码不是问题,我只是想看看是否有更好的方法。 好吧,我的回答的本质是,避免编写此代码的唯一方法是让其他人编写它(但实际上几乎所有代码都是这种情况)——你成功地做到了;) 你能把 null 放在 Set 中吗?如果是这样,此代码将 NPE。不过,我不确定原始海报想要对 null 做什么。我想从结果数组中省略它们。 @davidsheldon 有效备注。如果实现支持它,您可以将 null 放入 Set (显然,是的,但这就是 Set 的 Javadoc 定义的)。 HashSet 和 TreeMap 在尝试添加 null 时会抛出 NPE。不过,在 set 包含 null 的情况下抛出 NPE 似乎是要走的路,当然还有这种行为的适当文档 - 我们都彻底记录了,不是吗;) 不太正确。 HashSet 允许 nullTreeSet 将允许 null 如果已指定可以处理 null 的自定义 Comparator。但确实,最好的行为是如果集合包含null,则让代码抛出NullPointerException【参考方案8】:

不;你必须遍历它们。对不起。

【讨论】:

仔细想想就明白了。 int 不是对象,因此将一个类型转换为另一个是行不通的。 您无法从整数的 HashSet 中获取整数数组似乎很奇怪,自动装箱不应该启动并允许您这样做吗?这不像 HashSet 包含多种类型,它们都是整数所以(据我所知),这不是问题。 集合只能保存对象(在您的情况下为整数)。因此,有一个特殊的方法来获取一个整数数组是很奇怪的(其他原始类型需要相应的方法)。自动装箱没有帮助,因为这只适用于单个原始对象转换。请记住,实际的类(由于类型擦除)是 HashSet,而不是 HashSet(只是一个编译时概念)。 @MatthewFlaschen 不会键入擦除导致实际类是 HashSet? -docs.oracle.com/javase/tutorial/java/generics/erasure.html

以上是关于如何将 Java HashSet<Integer> 转换为原始 int 数组?的主要内容,如果未能解决你的问题,请参考以下文章

java:Set对象TreeSet有序子类,HashSet无序子类,重复对象二

为啥 Java 中的 HashSet 占用这么多内存?

java treeset和hashset如何判断元素是不是相同

Java 中 HashSet 的 removeAll 性能分析

Java中HashMap,HashSet是线程安全的吗,ArrayList是线程不安全的那如何避免其出异常?

如何通过构造初始化HashSet值?