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

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

hashset.toArray();

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

void doSomething(int[] arr)

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

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

【问题讨论】:

    标签: java arrays int hashset


    【解决方案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
          猜你喜欢
          • 2012-08-15
          • 2015-10-02
          • 1970-01-01
          • 2016-09-18
          • 2010-10-27
          • 1970-01-01
          • 2021-08-20
          相关资源
          最近更新 更多