Java基础教程

您所在的位置:网站首页 java列表添加元素 Java基础教程

Java基础教程

2023-03-13 03:54| 来源: 网络整理| 查看: 265

集合概述

Java中的集合,指一系列存储数据的接口和类,可以解决复杂的数据存储问题. 导包:import java.util.*;

简化的集合框架图如下:

List·列表

ArrayList

List是一个接口:

public interface List extends Collection{...}

ArrayList是最常用的一种List的子类(当然也实现了其他接口,也继承了父类)。

public class ArrayList extends AbstractList implements List, 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使用泛型

JDK 1.5之后,引入了泛型,可指定列表内元素的类型。类型不符合的元素不允许加入数组,这样就能再编译阶段发现错误,避免运行时出错的尴尬。

// 开团 List _泰国五日游 = new ArrayList(); …… // 混入 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 lst = new ArrayList(); 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 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 lst = new ArrayList(); lst.add("孙行者"); lst.add("猪八戒"); lst.add("沙悟净"); // 解决线程安全问题 List 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 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 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 synList = Collections.synchronizedList(lst); LinkedList

ArrayList使用数组实现,查询快,增删慢; LinkedList使用链表实现,查询慢,增删快,适用于经常插入、删除大量数据的场合,适合采用迭代器Iterator遍历。 如果仅仅是在列表末尾插入数据,LinkedList的效率低于ArrayList,因为LinkedList调用add时需要创建对象,而ArrayList只是在容量不够时才扩容。

LinkedList实现了List和Deque(双端队列)接口。

public class LinkedList extends AbstractSequentialList implements List, Deque, 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 link = new LinkedList(); // 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 stack = new ArrayDeque(); 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 queue = new ArrayDeque(); 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]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3