Java 中的 List —— 有序序列
List 在 java 中是个有序序列:
一、容量
ArrayList 中有一个容量概念,表示基础数组的大小(无参时默认为 10)。在需要的时候(比如 add操作)会自动增加其容量。LinkedList 没有这个概念。
TreeMap 也有容量,默认是 16.
二、改善的 search 方法
LinkedList 与 ArrayList 都很低效O(N)。比如 Collection 的 contain 和 remove 方法而言。他们均花费线性时间。下面对存、取、查找这三类情况进行比较:
- 访问数组中第 n 个数据的时间花费是 O(1) (类似地 HashMap 中通过 key 访问 value,但其存取都是 O(1) ,因为其索引是无序的,而数组是有序的索引),但是要在数组中查找一个指定的数据则是 O(N) 。当向数组中插入或者删除数据的时候,最好的情况是在数组的末尾进行操作,时间复杂度是 O(1) ,但是最坏情况是插入或者删除第一个数据,时间复杂度是 O(N) 。 在数组的任意位置插入或者删除数据的时候,后面的数据全部需要移动,移动的数据还是和数据个数有关所以总体的时间复杂度仍然是 O(N) 。
- 在链表中查找第 n 个数据以及查找指定的数据的时间复杂度是 O(N) ,但是链表插入和删除数据的时间复杂度是 O(1) ,因为只需要调整指针就可以。
- 堆栈实现了一种后进先出的语义 (LIFO) ,可以使用数组或者是链表来实现它。队列实现了先入先出的语义 (FIFO) 。队列也可以使用数组和链表来实现
提高运行效率 O(logn),可以使用 Collections.binarySearch(List list),二分法进行查找,需要对原集合/数组进行排序(双枢纽快速排序 O(n log(n))。
注意:
Collections.binarySearch 不支持 Set 集合,因为 HashSet/LinkedHashSet 使用的是哈希表,查询值(的位置/是否存在)只需要 比较哈希值,时间效率是 O(1)。因此不需要二分搜索法查找。
arrayList.add(311);
arrayList.add(233);
arrayList.add(999);
arrayList.add(777); arrayList.sort((o1, o2) -> o1 - o2); int index = Collections.binarySearch(arrayList, 777);
if (index >= 0) {
System.out.printf("找到了,索引为%s", index);
}
三、改善的 remove 方法(此方法对 ArrayList 无效,ArrayList 由于 remove 会改变数组结构,结构重组将花费大量时间。)
foreach 增强 for循环,抛异常
public static void removeEvensVer2(List<Integer> lst) {
for(Integer x : lst) {
if (x % 2 == 0)
lst.remove(x);
}
}
抛异常
java.util.ConcurrentModificationException
正的 for 循环,这会删除下标为偶数的元素,因为每次删除后,后面的元素的下标全部减1,相当于元素位置全部左移一位,再次删除时,会跳过一个元素进行删除。
for(int i = 0;i < list.size();i++){
list.remove(i);
}
倒的 for循环(全部删除)
for(int i = list.size()-1 ;i >= 0 ;i--){
list.remove(i);
}
新建一个要删除的List,最后一起删除。list.removeAll(deleteList)。
使用 while循环(但是这个方法对于 LinkedList 来说有几个糟糕的操作:1,使用 get方法,去遍历,在遍历的时候 get也花费线性时间。2,remove 同理,remove方法本身也花费线性时间)
public static void removeEvensVer1(List<Integer> lst) {
int i = 0;
while (i < lst.size())
if (lst.get(i) % 2 == 0)
lst.remove(i);
else
i++;
}
迭代器自带的 remove 处理 LinkedList:
当迭代到其节点时处理 remove 该节点的元素,仅花费常数时间。此外,LinkedList 除了 Collection 借口提供的 iterator方法之外, 还有扩展的 listIterator() 返回一个扩展接口 ListIterator<E>,具有 hasPrevious() pevious() add(Anytype x) set(AnyType newVal) 方法。主要方便从末尾向前迭代,和在迭代时添加和改变值(对于 LinkedList 改变和添加值花费较少。)
public static void removeEvensVer3(List<Integer> lst) {
Iterator<Integer> itr = lst.iterator();
while (itr.hasNext())
if (itr.next() % 2 == 0)
itr.remove();
}
四、排序
对于有序序列,可以使用 Collections.sort(List<T> list, Comparator<? super T> c) 按照自己的要求进行排序。
对于 TreeSet/TreeMap 基于红黑树数据结构,可以按照元素的自然顺序,或者创建 set 时提供的 Comparator 进行排序。
五、 ArrayList 与 LinkedList、Array 的区别
Array 固定长度,可以包含 primitives 基础类型与对象了;
ArrayList 基于数组结构,是大小可变数组的实现。ArrayList 只能包含 对象,可以使用泛型;
LinkedList 基于双向链表结构,List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列 (实现了 Queue 与 Deque 接口)。
Java 中的 List —— 有序序列的更多相关文章
- Java中集合的有序问题
Java中的容器主要包括两方面: Collection:List.Set.queue Map:HashMap.treeMap: 一. Collection 1. Set TreeSet:基于红黑树实现 ...
- Java中List Set Map 是否有序等总结
1.Collection List Set Map 区别记忆 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文 ...
- LeetCode 81. Search in Rotated Sorted Array II(在旋转有序序列中搜索之二)
Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this ...
- LeetCode 33. Search in Rotated Sorted Array(在旋转有序序列中搜索)
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- 【java虚拟机序列】java中的垃圾回收与内存分配策略
在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...
- java中Map,List与Set的区别(转)
Set,List,Map的区别 java集合的主要分为三种类型: Set(集) List(列表) Map(映射) 要深入理解集合首先要了解下我们熟悉的数组: 数组是大小固定的,并且同一个数组只能存放类 ...
- Java中Set Map List 的区别
java中set map list的区别: 都是集合接口 简要说明 set --其中的值不允许重复,无序的数据结构 list --其中的值允许重复,因为其为有序的数据结构 map--成对的数据结构 ...
- Java中Comparable和Comparator接口区别分析
Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...
- Java中的经典算法之选择排序(SelectionSort)
Java中的经典算法之选择排序(SelectionSort) 神话丿小王子的博客主页 a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕.也就是:每一趟 ...
随机推荐
- HBuilder的扩展插件开发暴露了一个事实:其实不能实现写一次代码实现跨平台App生成
HBuilder的扩展插件开发,原来并不能生成单独的插件jar,而是以源码 - 类的形式进行开发,这其实就要求必须使用离线打包. 事实上,开发顺序应该是:先弄好离线打包框架,然后在AS里进行扩展插件开 ...
- php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法
php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法 解决办法, 通过 insert 命令的方式进行创建. 创建数据库用户: $sql= "insert ...
- self.location.href
self.location.href;//当前页面打开URL页面 window.location.href;//当前页面打开URL页面 this.location.href;//当前页面打开URL页面 ...
- [Java] Windows/Linux路径不同时,统一war的最简办法
作者: zyl910 一.缘由 在项目开发时,因为运行环境的不同,导致有时得分别为不同的环境,切换配置参数打不同war包.但手工切换配置文件的话,不仅费时费力,而且容易出错. 有些打包工具支持配置切换 ...
- logback配置异步日志
<appender name="FILE" class= "ch.qos.logback.core.rolling.RollingFileAppender" ...
- Linux-task_struct和文件系统及管道的关系
推荐:文件描述符和文件指针的关系 fs_struct 记录该进程所在文件系统等信息. files_struct 记录该进程当前打开的所有文件等信息,其中有一个元素为数组,数组索引是文件描述符,数组元素 ...
- CAP二十年:“规则”变了
本文是原文https://www.cnblogs.com/cobbliu/p/7494961.html的译文,原链接:http://www.infoq.com/cn/articles/cap-twel ...
- 【Apache】Apache的安装和配置
Apache是世界非常流行的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. Apache在Win7上的安装 下载apa ...
- (原创)Rocketmq分布式消息队列的部署与监控
-------------------------------------------------------------------------------------------- 一.Rocke ...
- Java里进制转换(二进制、八进制、十进制、十六进制)
// 十进制转其它进制(二进制,八进制,十六进制) int k = 17; System.out.println(Integer.toBinaryString(k));// 转二进制 System.o ...