集合概述

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);
}
}
}

迭代器原理gif:https://www.cnblogs.com/tigerlion/p/10706386.html

更多方法

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(列表)的更多相关文章

  1. Java基础教程(18)--继承

    一.继承的概念   继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...

  2. Java基础教程:泛型基础

    Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...

  3. Java基础教程:HashTable与HashMap比较

    Java基础教程:HashTable与HashMap比较 1.  关于HashMap的一些说法: a)  HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体.HashMap的底层结 ...

  4. Java基础教程:对象比较排序

    Java基础教程:对象比较排序 转载请标明出处:http://blog.csdn.net/wangtaocsdn/article/details/71500500 有时候需要对对象列表或数组进行排序, ...

  5. Java基础教程:面向对象编程[3]

    Java基础教程:面向对象编程[3] 内容大纲 基础编程 获取用户输入 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入.我们可以查看Ja ...

  6. Java基础教程(12)--深入理解类

    一.方法的返回值   当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...

  7. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  8. Java基础教程:网络编程

    Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...

  9. Java基础教程(5)--变量

    一.变量 1.变量的定义   正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...

  10. Java基础教程:Lambda表达式

    Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...

随机推荐

  1. ZooKeeper CentOS7上安装

    下载http://www.apache.org/dyn/closer.cgi/zookeeper(我下的是zookeeper-3.4.14) 1.创建 /usr/local/services/zook ...

  2. NB-IoT DTU是什么 NB-IoT的优势有哪些

    NB-IoT DTU是什么 NB-IoT DTU是一种采用NB-IoT技术实现数据远距离无线传输功能的终端设备,采用工业级的硬件设施和工业级的32位高性能通信处理器,工业级的无线数据传输模块,可以自动 ...

  3. 老板下了死命令,要把日志系统切换到Logback

    Log4j 介绍过了,SLF4J 也介绍过了,那接下来,你懂的,Logback 就要隆重地登场了,毕竟它哥仨有一个爹,那就是巨佬 Ceki Gulcu. 就在昨天,老板听我说完 Logback 有多牛 ...

  4. Java Web中解决乱码的方式

    Java Web中解决乱码的方式 方式一:添加编码过滤器 package com.itmacy.dev.filter; import javax.servlet.*; import javax.ser ...

  5. .NET CORE QuartzJob定时任务+Windows/Linux部署

    前言 以前总结过一篇基于Quartz+Topshelf+.netcore实现定时任务Windows服务 https://www.cnblogs.com/gt1987/p/11806053.html.回 ...

  6. html+vue.js 实现分页可兼容IE

    当功能比较简单,在单一html中使用vue.js分页展示数据,并未安装脚手架,或使用相关UI框架,此时需要手写一个分页器,不失为最合理最便捷的解决方案, 先看一下实现效果: 上代码: 1.简单搞一搞 ...

  7. Matlab批量绘制图像并保存

    author:ZKe ------------------------------- 以下是一个txt文件,每行11个字段,第一个字段是日期,后面10个是用户id和对应今天发表微博数,所有字段用制表符 ...

  8. 18 socket

    18 socket 推荐: http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml Socket=Ip address+ TC ...

  9. Core WebApi项目快速入门(一):环境部署

    1.WebApi新建与部署 1.1 新建Core WebApi工程 1.2 部署 1.2.1 IIS部署 首先以文件方式发布应用程序,然后下载依赖.net core运行时及host安装包 在iis中看 ...

  10. Java实现FTP跨服务器文件操作

    在过去的几年工作中,曾经多次需要把文件上传到单独的服务器,而程序是在单独的服务器上部署的,在进行文件操作的时候就需要跨服务器进行操作包括:文件上传.文件下载.文件删除等.跨服务器文件操作一般是需要FT ...