Java中为什么需要集合框架?

8

既然数组可以完成所有的数据操作(排序/添加/删除),而且数组在内存消耗和性能方面都比集合更好,那么Java中为什么需要集合框架呢?

有没有人能给我一个实时的数据导向示例,展示这两种实现方法之间的差异(数组/集合)。

10个回答

27
  • 数组不可调整大小。
  • Java集合框架提供了许多不同的有用数据类型,如链表(允许在常数时间内任意位置插入),可调整大小的数组列表(类似于Vector但更酷),红黑树,基于哈希的映射(类似于Hashtable但更酷)。
  • Java集合框架提供了抽象,因此您可以将列表称为List,无论是由数组列表还是链表支持;您可以将映射/字典称为Map,无论是由红黑树还是哈希表支持。

换句话说,Java集合框架允许您使用正确的数据结构,因为一个尺寸并不适合所有情况。


2
+1 绝对是更好的答案。我删除了我的笨拙回答。 - Adeel Ansari
3
如果我不试图成为“最快的枪手”,我可能可以进一步改进它(讨论何时使用哪些,Google Collections等),但我仍会尽力而为。 :-P - C. K. Young
数组不可调整大小,那么自从ArrayList出现以来,它们存在的意义是否还有任何理由呢? - Sreekanth Karumanaghat
@Sreekanth 是的,ArrayList 在幕后使用数组,没有数组,ArrayList 就不存在了。此外,许多语言特性直接使用数组(例如,注释参数可以是数组类型,但不能是 ArrayList)。 - C. K. Young

6

有几个原因:

  • Java的集合类提供了比数组更高级别的接口。
  • 数组具有固定大小。而集合(例如ArrayList)具有灵活的大小。
  • 在原始数组上高效地实现复杂的数据结构(例如哈希表)是一项艰巨的任务。标准的HashMap可以免费提供这一点。
  • 对于同一组服务,您可以选择不同的实现:ArrayList vs. LinkedList,HashMap vs. TreeMap,synchronized等。
  • 最后,数组允许协变:由于只能在运行时检测到的类型错误,设置数组元素不能保证成功。泛型可以解决这个数组问题。

看一下下面这个片段,它说明了协变问题:

  String[] strings = new String[10];
  Object[] objects = strings;

  objects[0] = new Date();  // <- ArrayStoreException: java.util.Date

不,您不能将 objects 强制转换为 Integer[],因为它实际上是 String[] 类型;在那一点上,您会得到 ClassCastException - C. K. Young

2

集合类(如Set、List和Map实现)更接近于“问题空间”。它们可以让开发人员更快地完成工作,并提交更易读/易维护的代码。


1

对于集合API中的每个类,都有不同的答案回答您的问题。以下是一些例子。

LinkedList:如果您从数组中间删除一个元素,则需要付出将所有右侧元素移动的代价。但使用链表则不需要。

Set:如果您尝试使用数组实现一个集合,添加元素或测试元素是否存在的时间复杂度为O(N)。但使用HashSet,则为O(1)。

Map:使用数组实现映射将具有与您假设的数组实现集合相同的性能特征。


0

这取决于您的应用程序需求。有许多类型的集合,包括:

  • HashSet
  • ArrayList
  • HashMap
  • TreeSet
  • TreeMap
  • LinkedList

例如,如果您需要存储键/值对,则如果基于数组,您将不得不编写大量自定义代码 - 而Hash*集合应该可以直接使用。像往常一样,选择适合工作的正确工具。


0

基本前提是“错误的”,因为Java在语言中引入接口之前就已经包含了Dictionary类...

集合提供了List,它们与数组有些相似,但它们提供了许多其他的东西。我假设你只是在谈论List(甚至Set),而将Map排除在外。

是的,使用数组可以获得与List和Set相同的功能,但是需要大量的工作。整个库的重点是用户不必自己实现常见的事物。

一旦您拥有每个人都使用的单个实现,就更容易证明花费资源进行优化。这意味着当标准集合被加速或其内存占用被减少时,所有使用它们的应用程序都可以免费获得改进。

每个事物的单个接口也简化了每个开发人员的学习曲线-没有无数种做同样事情的方法。

如果您想要一个随时间增长的数组,您可能不会在所有类中都放置增长代码,而是编写一个单独的实用程序方法来执行该操作。删除和插入等操作也是如此...

此外,数组不适合插入/删除操作,特别是当您希望 .length 成员反映实际内容数量的时候,您将花费大量时间来增加和缩小数组。数组也不适合用于集合,因为每次要进行插入以检查重复项时,您必须遍历整个数组。这会破坏任何感知效率。


0

0

Java Collections(Java集合)提供了不同的功能、可用性和便捷性。

当在应用程序中我们想要处理一组对象时,仅仅使用数组是不够的,或者说它们可能会导致一些繁琐的操作。

一个重要的区别就是可用性和便捷性,尤其是在需要时,集合会自动扩展大小:

集合提供了简化我们工作的方法。

每个集合都有其独特的特点:

  • List- 本质上是一个可变大小的数组;
    通常可以在任意位置添加/删除项目;
    项目的顺序是明确定义的(即您可以说给定项目在列表中的位置)。

    用途- 大多数情况下,您只需要存储或迭代“一堆东西”,然后再迭代它们。

  • Set- 事物可以“存在或不存在”-当您将项目添加到集合中时,没有关于该项目被添加了多少次的概念,并且通常没有排序的概念。

    用途- 记住“您已经处理过哪些项目”,例如在进行网络爬行时;
    对项目做出其他是或否的决策,例如“该项目是否为英语单词”,“该项目是否在数据库中?”,“该项目是否属于此类别?”等。

在这里,您可以根据情况找到每个集合的用途


0

集合框架比数组更高级,提供了重要的接口和类,通过使用它们,我们可以以更复杂的方式管理对象组,并使用特定集合已经提供的许多方法。

例如:

  • ArrayList - 它就像一个动态数组,即我们不需要声明其大小,它会随着我们添加元素而增长,随着我们从中删除元素而缩小,在程序运行时。
  • LinkedList - 它可以用来表示队列(FIFO)或甚至堆栈(LIFO)。
  • HashSet - 它通过哈希过程存储其元素。 HashSet 中元素的顺序不能保证。
  • TreeSet - 当需要存储大量排序元素并快速访问它们时,TreeSet 是最佳选择。
  • ArrayDeque - 它也可以用于实现先进先出(FIFO)队列或后进先出(LIFO)队列。
  • HashMap - HashMap 以键值对的形式存储数据,其中键和值都是对象。
  • Treemap - TreeMap 按升序存储键值对,从 TreeMap 中检索元素的速度非常快。

想要了解更多关于Java集合的知识,请查看这篇文章


0

集合是Java中的框架,您知道框架非常易于使用,而不是实现和使用它,您关心的是为什么我们不使用数组,因为数组有缺点,例如它是静态的,您必须至少在开始时定义行的大小,因此,如果您的数组很大,则会导致大量内存浪费。因此,您可以优先选择集合层次结构中的ArrayList。

复杂性是另一个问题,例如,如果您想要在数组中插入元素,则必须跟踪到定义索引,因此您可以使用LinkedList,所有函数都已实现,只需使用即可使您的代码更简单,并且您可以阅读集合层次结构的各种优点。


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