关于Java集合最被关注的10 个问题

下面是stackoverflow关于Java集合方面讨论最多的几个问题,在这里整理出来供大家参考。

1.关于LinkList和ArrayList

  • ArrayList:内部实现是个数组,其中的元素可以通过index获取。但是,如果一个数组满了的话,我们就必须重新分配一个更大的数组然后把所有元素移动到这个新数组,其时间复杂度为O(n)。添加或删除一个元素时也需要移动数组中的其它元素。这就是ArrayList的缺点。
  • LinkedList:是一个双向链表。因此如果我们要获取中间元素的话,我们就需要从头开始遍历;另一方面,添加或删除一个元素就变得很简单,因为只需要对这个链表本身操作即可。

总的来说,最坏的情况下两者时间复杂度的对比如下:

                   | Arraylist | LinkedList
 ------------------------------------------
 get(index)        |    O(1)   |   O(n)
 add(E)            |    O(n)   |   O(1)
 add(E, index)     |    O(n)   |   O(n)
 remove(index)     |    O(n)   |   O(n)
 Iterator.remove() |    O(n)   |   O(1)
 Iterator.add(E)   |    O(n)   |   O(1)

除了考虑时间复杂度之外,当List比较大时,空间复杂度也不可忽略:

  • LinkList:每个节点还需要额外的两个指针,分别指向前一个节点和下一个节点
  • ArrayList:只需要一个数组

更多比较信息...

2.最有效移除集合元素的方式

唯一正确的移除集合元素的方式就是使用Iterator.remove()方法:

Iterator<Integer> itr = list.iterator();
while(itr.hasNext()) {
   // do something
   itr.remove();
}

  下面这种处理方式是错误的,会报出这么一个异常:ConcurrentModificationException
for(Integer i: list) {
  list.remove(i);
}

3.如何将一个List转换成一个int[] 数组?

     最简单的方式就是使用Apache Commons Lang工具包下的ArrayUtils
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));

如果用jdk的话是没有捷径的,注意我们不能使用List.toArray()方法,因为这样得到的是Integer[],正确的方法应该是:

int[] array = new int[list.size()];
for(int i=0; i < list.size(); i++) {
  array[i] = list.get(i);
}
4.如何将int[] 转换成List?
     和上面类似,我们可以使用ArrayUtils工具类:
List list = Arrays.asList(ArrayUtils.toObject(array));

或者依然没有捷径:

int[] array = {1,2,3,4,5};
List<Integer> list = new ArrayList<Integer>();
for(int i: array) {
  list.add(i);
}

5.最好的过滤集合的方法?  

    当然,最方便最好的方式就是使用第三方jar包,比如 Guava or Apache Commons Lang ,这两者都提供了filter()方法。在jdk中,事情就变得没那么简单了(不过Java8已经支持Predicate了),但是在Java8之前,比较通常的方式是我们必须遍历集合中的所有元素:
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()) {
   int i = itr.next();
   if (i > 5) { // filter all ints bigger than 5
      itr.remove();
   }
}

但是我们可以模拟GuavaApache Commons Lang,通过引入一个新的Predicate接口,这是很多高级工程师的方法:

public interface Predicate<T> {
   boolean test(T o);
}

public static <T> void filter(Collection<T> collection, Predicate<T> predicate) {
    if ((collection != null) && (predicate != null)) {
       Iterator<T> itr = collection.iterator();
          while(itr.hasNext()) {
            T obj = itr.next();
            if (!predicate.test(obj)) {
               itr.remove();
            }
        }
    }
}
filter(list, new Predicate<Integer>() {
    public boolean test(Integer i) {
       return i <= 5;
    }
});

6.把List转换成Set的最简单的方式有两种方式:

Set<Integer> set = new HashSet<Integer>(list);
Set<Integer> set = new TreeSet<Integer>(aComparator);
set.addAll(list);

7.如何移除ArrayList中的重复元素  

    和上面方法类似,如果不关心顺序的话:
ArrayList** list = ... // initial a list with duplicate elements
Set<Integer> set = new HashSet<Integer>(list);
list.clear();
list.addAll(set);

如果关心顺序,把上面那个HashSet换成LinkedHashSet即可。

8.给集合排序    
   给集合排序的实现方法有很多种
	1.Collections.sort():进行一次排序
	2.PriorityQueue :始终保持队列的顺序,但是只能从队列的头获取元素
	3.TreeSet:始终保持队列的顺序,元素不重复,你可以从最顶端或最低端获取元素,但也不能随机获取元素
9.Collections.emptyList() vs new Instance     
    上面两个方法都会返回空的List,但是Collections.emptyList()返回的List是不可变的,每次方法调用不会重新创建一个实例,而是复用原来的实例(即单例模式),所以这样效率会高些。
10.Collections.copy     
    有两种方式复制一个List,第一种:
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList);

第二种是利用Collections.copy()方法:

ArrayList<Integer> dstList = new ArrayList<Integer>(srcList.size());
Collections.copy(dstList, srcList);

那两者有何区别呢?  

    如果目标集合(dstList)小于源集合,使用Collections.copy()会抛出IndexOutOfBoundsException,那它有什么好处呢?首先它保证运行效率和集合大小线性相关,第二就是可以实现集合的重用。
 
时间: 2024-10-14 10:04:03

关于Java集合最被关注的10 个问题的相关文章

2016.3.9-3.10(java集合框架)

3.9 集合框架有什么作用? 集合框架其主要功能是用来将存储的数据以某种结构组织,并以特定的方式来访问这些数据. Java集合框架中有哪些存储方式? Java集合框架中的对象容器,按照对象在其中的存储方式,分为Set.List.和Map三种类型. Set类型对象没有顺序,且不能重复: List类型对象容器中的对象按照索引顺序排序,而且可以有重复的对象: Map类型对象容器中的元素包含一对“键对象-值对象”映射,其中键对象不能重复,值对象可以重复. 以上三种存储方式对应Java集合框架中Set.L

第10篇-JAVA 集合框架-JAVA 泛型

第10篇-JAVA 集合框架-JAVA 泛型 每篇一句 :所有的不甘,都是因为还心存梦想 初学心得: 不是每件事都注定会成功,但是每件事都值得一试 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-15| JAVA 集合框架/JAVA 泛型 ] 1.JAVA 集合框架概念 通俗的说,集合就是一个存放数据的容器,准确的说,就是放数据对象引用的容器 数组和集合都是容器,有何不同? 数组长度固定,集合长度可变 数组只能存放相同类型的数据,集合可以存放不同类型的数据 数组可存放简单数据

Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 Java 集合系列 05 Vector详细介绍(源码解析)和使用示例 Java 集合系列 06 Stack详细介绍(源码解析)和使用示例 Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和

Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例

概要 这一章,我们对HashMap进行学习.我们先对HashMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashMap.内容包括:第1部分 HashMap介绍第2部分 HashMap数据结构第3部分 HashMap源码解析(基于JDK1.6.0_45)第3.1部分 HashMap的“拉链法”相关内容第3.2部分 HashMap的构造函数第3.3部分 HashMap的主要对外接口第3.4部分 HashMap实现的Cloneable接口第3.5部分 HashMap实现的Seria

java集合框架10——TreeMap和源码分析(一)

前面讨论完了HashMap和HashTable的源码,这一节我们来讨论一下TreeMap.先从整体上把握TreeMap,然后分析其源码,深入剖析TreeMap的实现. 1. TreeMap简介 TreeMap是一个有序的key-value集合,它内部是通过红-黑树实现的,如果对红-黑树不太了解,请先参考下这篇博文:红-黑树.下面我们先来看看TreeMap的继承关系: java.lang.Object ? java.util.AbstractMap<K, V> ? java.util.TreeM

JAVA集合框架

收藏 查看我的收藏 146有用+1 56 编辑 Java,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称.用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台.动态的Web.Internet计算.从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器现在均支持Java applet.集合框架是为表示和操作集合而规定的一种统一的标准的体系结构.任何集合框架都包含三大块内容:对外的接口.接口的实

Java集合干货系列-(一)ArrayList源码解析

前言 今天来介绍下ArrayList,在集合框架整体框架一章中,我们介绍了List接口,ArrayList继承了AbstractList,实现了List.ArrayList在工作中经常用到,所以要弄懂这个类是极其重要的.构造图如下:蓝色线条:继承绿色线条:接口实现 正文 ArrayList简介 ArrayList定义 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomA

浅入深出之Java集合框架(上)

Java中的集合框架(上) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架(下)>. 目录: 浅入深出之Java集合框架(上) 浅入深出之Java集合框架(中)   努力赶制中..关注后更新会提醒哦! 浅入深出之Java集合框架(下) 努力赶制中..关注后更新会提醒哦! 一.集合概述 1)集合的概念 现实生活中的集合:很多事物凑在一起. 数学中的集合:具有共同属性的事物的总体

浅入深出之Java集合框架(中)

Java中的集合框架(中) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架(下)>. 目 录 浅入深出之Java集合框架(上) 浅入深出之Java集合框架(中)   浅入深出之Java集合框架(下) 努力赶制中..关注后更新会提醒哦! 前 言 在<浅入深出之Java集合框架(上)>中介绍了List接口和Set接口的基本操作,在这篇文章中,我将介绍关于Map接口的基