Java基础教程——List(列表)
集合概述
Java中的集合,指一系列存储数据的接口和类,可以解决复杂的数据存储问题.
导包:import java.util.*;
简化的集合框架图如下:
List·列表
ArrayList
List是一个接口:
public interface List<E> extends Collection<E>{...}
ArrayList是最常用的一种List的子类(当然也实现了其他接口,也继承了父类)。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{...}
ArrayList用法类似于数组,且其容量可按需要动态调整,亦被称为动态数组。
数组最大的痛点是大小固定(可以改变,但是很麻烦)
ArrayList底层是用数组实现的,所以名字里带了个数组(Array)。
示例:泰国旅行团
本示例展示了在List中使用泛型的必要性。
设定:泰国旅行团,约定只收Girl,有一个Boy混入,编译没问题,接机(输出)时按Girl接收,会出错。
import java.util.ArrayList;
import java.util.List;
public class TestArrayList {
public static void main(String[] args) {
// 开团
List _泰国五日游 = new ArrayList();
Girl _g1 = new Girl();
Girl _g2 = new Girl();
Girl _g3 = new Girl();
_泰国五日游.add(_g1);
_泰国五日游.add(_g2);
_泰国五日游.add(_g3);
// 混入
Boy _b = new Boy();
_泰国五日游.add(_b);
System.out.println("...");
// 接机
for (int i = 0; i < _泰国五日游.size(); i++) {
Girl g = (Girl) _泰国五日游.get(i);
}
}
}
class Boy {
}
class Girl {
}
代码没错,运行出错(对象本是Boy类型,偏要转成Girl类型---类型转换异常)
Exception in thread "main"
java.lang.ClassCastException
ArrayList<E>使用泛型
JDK 1.5之后,引入了泛型,可指定列表内元素的类型。类型不符合的元素不允许加入数组,这样就能再编译阶段发现错误,避免运行时出错的尴尬。
// 开团
List<Girl> _泰国五日游 = new ArrayList<Girl>();
……
// 混入
Boy _b = new Boy();
//提示代码有错误: _泰国五日游.add(_b);
遍历
import java.util.*;
public class ListTraversal {
public static void main(String[] args) {
m010Traversal();
m020线程安全版();
}
private static void m010Traversal() {
System.out.println("=====遍历");
List<String> lst = new ArrayList<String>();
lst.add("孙行者");
lst.add("猪八戒");
lst.add("沙悟净");
// (1)
for (int i = 0; i < lst.size(); i++) {
System.out.println("for遍历集合:" + lst.get(i));
}
// (2)
for (String s : lst) {
System.out.println("foreach遍历集合:" + s);
}
// (3)Iterator,迭代器。用于遍历(迭代访问)集合中的元素
Iterator<String> it = lst.iterator();
while (it.hasNext()) {
System.out.println("Iterator遍历:" + it.next());
}
// (4)Java 8:调用forEach()方法遍历集合
lst.forEach(s -> System.out.println("Lambda表达式遍历集合:" + s));
}
// API文档上说ArrayList不是同步的,即多线程环境下不安全
// Collections.synchronizedList(...)将其转为线程安全的列表
private static void m020线程安全版() {
System.out.println("=====线程安全版");
List<String> lst = new ArrayList<String>();
lst.add("孙行者");
lst.add("猪八戒");
lst.add("沙悟净");
// 解决线程安全问题
List<String> synList = Collections.synchronizedList(lst);
for (String s : synList) {
System.out.println("foreach遍历集合:" + s);
}
}
}
更多方法
Collection相关方法
这些方法属于Collection类,可以被子类继承,因此通用性较强,不仅List能用,Set也能用。
返回类型 | 方法名称 | 描述 |
---|---|---|
boolean | add(Object o) | 添加元素 |
int | size() | 获取元素个数 |
boolean | contains(Object o) | 判断是否存在指定元素 |
boolean | remove(Object o) | 删除元素 |
void | clear() | 清空 |
boolean | isEmpty() | 判空 |
Object[] | toArray() | 集合转数组 |
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class TestCollection {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add("s" + i);
}
System.out.println("size():" + list.size());
// 查找
boolean contains = list.contains("s1");
System.out.println("contains(Object o):" + contains);
boolean empty = list.isEmpty();
System.out.println("isEmpty():" + empty);
// 集合转数组
Object[] array = list.toArray();
System.out.println("toArray():" + Arrays.toString(array));
// 删除
list.remove("s1");
System.out.println("remove(Object o):" + list);
list.clear();
System.out.println("clear():" + list);
}
}
List相关方法
List的派生类对象可以使用,Set不可用。
都是和索引相关的方法:
返回类型 | 方法名称 | 描述 |
---|---|---|
void | add(int index, E element) | 指定位置添加元素 |
int | indexOf(Object o) | 获取指定元素的索引 |
E | set(int index, E element) | 替换指定位置的元素,返回更新前的元素 |
E | get(int index) | 获取指定索引的元素 |
E | remove(int index) | 删除指定索引的元素 |
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("s" + i);
}
list.add(3, "舍卫国");
int indexOf = list.indexOf("舍卫国");
System.out.println("List.indexOf(Object o):" + indexOf);
String set = list.set(0, "舍卫国赵长者");// 返回更新前的元素
System.out.println("List.set(int index, E element):" + set);
String get = list.get(0);
System.out.println("List.get(int index):" + get);
String remove = list.remove(3);// 返回被删除的元素
System.out.println("List.remove(int index):" + remove + list);
}
}
源码浅析:
ArrayList底层是通过数组实现,查询快、增删慢。API文档上说ArrayList不是同步的,即多线程环境下不安全,但是效率高。
ArrayList每次扩容至1.5倍。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// >>1:右移动1位=除以2
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector
和ArrayList用法一致。
元素超过它的初始大小 | 线程安全 | 效率 | |
---|---|---|---|
ArrayList | *150% | × | 高 |
Vector | *200% | √ | 低 |
Vector是一个比较老的类,在JDK 1.0即已出现,不推荐使用(蓝桥杯的练习题中出现过Vector,在那道题中只要知道它的用法和ArrayList一样就行)。
虽然Vector是线程安全的,但是在线程安全方面也不推荐使用。推荐方案如下:
List<String> synList = Collections.synchronizedList(lst);
LinkedList
ArrayList使用数组实现,查询快,增删慢;
LinkedList使用链表实现,查询慢,增删快,适用于经常插入、删除大量数据的场合,适合采用迭代器Iterator遍历。
如果仅仅是在列表末尾插入数据,LinkedList的效率低于ArrayList,因为LinkedList调用add时需要创建对象,而ArrayList只是在容量不够时才扩容。
LinkedList实现了List和Deque(双端队列)接口。
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
特色方法(此时不能使用多态):
特色方法 | 解释 |
---|---|
addFirst() | 头部添加 |
addLast() | 尾部添加 |
removeFirst() | 头部删除 |
removeLast() | 尾部删除 |
push() | 入栈,等效于addFirst() |
pop() | 出栈,等效于removeFirst() |
offer() | 入队列,等效于addLast() |
poll() | 出队列,等效于removeFirst() |
import java.util.LinkedList;
public class TestLinkedList {
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
// addFirst:头部添加数据
link.addFirst("A");
link.addFirst("B");
link.addFirst("C");
link.removeFirst();
System.out.println(link);
// addLast:尾部添加数据
link.addLast("A");
link.addLast("B");
link.addLast("C");
link.removeLast();
System.out.println(link);
link.clear();// 清空
// push:将元素推入栈,等效于addFirst()
link.push("A");
link.push("B");
link.push("C");
// pop:出栈,调用的是removeFirst()
link.pop();
System.out.println("栈" + link);
link.clear();// 清空
// 将指定元素添加到此列表的末尾(最后一个元素)。
// offer:入队列:调用的是add方法,add又调用linkLast,和addLast一样
link.offer("A");
link.offer("B");
link.offer("C");
// poll:出队列:调用的是removeFirst()
link.poll();
System.out.println("队列" + link);
}
}
[B, A]
[B, A, A, B]
栈[B, A]
队列[B, C]
*ArrayDeque·栈和队列
- 栈:先进后出
- 队列:先进先出
Deque(双端队列),是Queue的子接口,其实现类ArrayDeque和ArrayList的实现机制相似,使用Object[]数组存储集合元素,当容量不足时,可以重新分配数组。
ArrayDeque可以当做栈和队列使用。
import java.util.*;
public class TestArrayDeque {
public static void main(String[] args) {
m030栈();
m040队列();
}
static void m030栈() {
System.out.println("=====栈");
// push,pop(poll也可以)
Deque<String> stack = new ArrayDeque<String>();
stack.push("A");
System.out.println(stack);// [A]
stack.push("B");
System.out.println(stack);// [B, A]
stack.push("C");
System.out.println(stack);// [C, B, A]
System.out.println("peek()访问第一个元素:" + stack.peek());// C
System.out.println("pop()弹出:" + stack.pop());// C
System.out.println(stack);// [B, A]
}
static void m040队列() {
System.out.println("=====队列");
// offrt,poll(pop也可以)
Deque<String> queue = new ArrayDeque<String>();
queue.offer("A");// [A]
System.out.println(queue);
queue.offer("B");// [A, B]
System.out.println(queue);
queue.offer("C");// [A, B, C]
System.out.println(queue);
System.out.println("peek()访问第一个元素:" + queue.peek());// A
System.out.println("poll()弹出:" + queue.poll());// A
System.out.println(queue);// [B, C]
}
}
运行结果:
=====栈
[A]
[B, A]
[C, B, A]
peek()访问第一个元素:C
pop()弹出:C
[B, A]
=====队列
[A]
[A, B]
[A, B, C]
peek()访问第一个元素:A
poll()弹出:A
[B, C]
Java基础教程——List(列表)的更多相关文章
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础教程:HashTable与HashMap比较
Java基础教程:HashTable与HashMap比较 1. 关于HashMap的一些说法: a) HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体.HashMap的底层结 ...
- Java基础教程:对象比较排序
Java基础教程:对象比较排序 转载请标明出处:http://blog.csdn.net/wangtaocsdn/article/details/71500500 有时候需要对对象列表或数组进行排序, ...
- Java基础教程:面向对象编程[3]
Java基础教程:面向对象编程[3] 内容大纲 基础编程 获取用户输入 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入.我们可以查看Ja ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
随机推荐
- ZooKeeper CentOS7上安装
下载http://www.apache.org/dyn/closer.cgi/zookeeper(我下的是zookeeper-3.4.14) 1.创建 /usr/local/services/zook ...
- NB-IoT DTU是什么 NB-IoT的优势有哪些
NB-IoT DTU是什么 NB-IoT DTU是一种采用NB-IoT技术实现数据远距离无线传输功能的终端设备,采用工业级的硬件设施和工业级的32位高性能通信处理器,工业级的无线数据传输模块,可以自动 ...
- 老板下了死命令,要把日志系统切换到Logback
Log4j 介绍过了,SLF4J 也介绍过了,那接下来,你懂的,Logback 就要隆重地登场了,毕竟它哥仨有一个爹,那就是巨佬 Ceki Gulcu. 就在昨天,老板听我说完 Logback 有多牛 ...
- Java Web中解决乱码的方式
Java Web中解决乱码的方式 方式一:添加编码过滤器 package com.itmacy.dev.filter; import javax.servlet.*; import javax.ser ...
- .NET CORE QuartzJob定时任务+Windows/Linux部署
前言 以前总结过一篇基于Quartz+Topshelf+.netcore实现定时任务Windows服务 https://www.cnblogs.com/gt1987/p/11806053.html.回 ...
- html+vue.js 实现分页可兼容IE
当功能比较简单,在单一html中使用vue.js分页展示数据,并未安装脚手架,或使用相关UI框架,此时需要手写一个分页器,不失为最合理最便捷的解决方案, 先看一下实现效果: 上代码: 1.简单搞一搞 ...
- Matlab批量绘制图像并保存
author:ZKe ------------------------------- 以下是一个txt文件,每行11个字段,第一个字段是日期,后面10个是用户id和对应今天发表微博数,所有字段用制表符 ...
- 18 socket
18 socket 推荐: http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml Socket=Ip address+ TC ...
- Core WebApi项目快速入门(一):环境部署
1.WebApi新建与部署 1.1 新建Core WebApi工程 1.2 部署 1.2.1 IIS部署 首先以文件方式发布应用程序,然后下载依赖.net core运行时及host安装包 在iis中看 ...
- Java实现FTP跨服务器文件操作
在过去的几年工作中,曾经多次需要把文件上传到单独的服务器,而程序是在单独的服务器上部署的,在进行文件操作的时候就需要跨服务器进行操作包括:文件上传.文件下载.文件删除等.跨服务器文件操作一般是需要FT ...