集合
1 Collection接口
1.1 集合概述
集合是一个装对象的容器。集合中只能存放引用数据类型的对象。集合中有一些大小是固定的,有一些是不固定的。有一些是有序的,有些是无序的。
有些可以有重复元素,有一些不可以有重复元素
1.2 集合常用方法
public static void main(String[] args) { // 创建集合对象 Collection<String> coll = new ArrayList<>(); // 添加元素 coll.add("吴京"); coll.add("王源"); coll.add("丁真"); coll.add("迪丽热巴"); coll.add("刘浩存"); coll.add("田晓威"); // 清空集合 // coll.clear(); boolean contains = coll.contains("刘浩存"); System.out.println(contains); // 判断集合是否为空 boolean empty = coll.isEmpty(); System.out.println(empty); // 移除指定的元素 boolean remove = coll.remove("田晓威"); System.out.println(remove); // 获取集合的实际元素个数 int size = coll.size(); System.out.println(size); // 把集合转换成数组 String[] array = coll.toArray(new String[0]); for (String o : array) { System.out.println(o); } System.out.println(coll); }
1.3 List接口
1.3.1 List接口的特点
有序的集合
方法具有索引
允许重复的元素
1.3.2 List接口带有索引的方法
public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("郭靖"); list.add("洪七公"); list.add("黄蓉"); list.add("欧阳锋"); list.add("欧阳克"); list.add("黄蓉"); // 插入元素 list.add(3,"黄药师"); list.add(6,"周伯通"); // IndexOutOfBoundsException: 索引越界 // ArrayIndexOutOfBoundsException: 数组越界 // StringIndexOutOfBoundsException: 字符串越界 // list.add(9,"王重阳"); list.add("黄蓉"); // 获取指定索引处的元素 String s = list.get(4); System.out.println(s); // 获取指定元素首次出现的索引 找不到返回-1 int index = list.indexOf("杨过"); System.out.println(index); // 获取指定元素最后一次出现的索引 找不到返回-1 int indexOf = list.lastIndexOf("黄蓉"); System.out.println(indexOf); // 删除指定索引处的元素 String remove = list.remove(5); System.out.println(remove); // 替换指定索引处的元素 String set = list.set(6, "杨康"); System.out.println(set); // 截取子列表 包头不包尾 List<String> strings = list.subList(2, 6); System.out.println(strings); System.out.println(list); }
1.3.3 ArrayList的特点
内部数据结构是数组
内存是连续的,具有索引
查询速度相对快
增删速度相对慢
异步线程不安全的集合
可以存放null
默认无参构造的初始容量是0
默认的初始容量是10
扩容是原来容量 + 原来容量 / 2
public static void main(String[] args) { ArrayList<String> arrayList = new ArrayList<>(14); arrayList.add("阿珍"); // 把ArrayList长度变成实际元素个数的长度 arrayList.trimToSize(); }
1.3.4 实现ArrayList练习
package cn.javasm.demo; import java.util.Arrays; import java.util.Objects; /** * 模拟实现ArrayList */ public class ArrayListDemo { // 存储数据的数组 private String[] data; // 实际元素个数 private int size; // 定义无参构造 public ArrayListDemo(){ // 默认长度是10 data = new String[10]; } // 定义有参构造,用户可以根据参数选择初始默认容量 public ArrayListDemo(int len){ if (len < 0) throw new IllegalArgumentException(); data = new String[len]; } // 添加元素 public void add(String str){ // 判断是否需要扩容 if (size >= data.length){ grow(); } data[size++] = str; } /** * 扩容数组 */ private void grow() { if (data.length >= 1) data = Arrays.copyOf(data,data.length + (data.length >> 1)); else data = Arrays.copyOf(data,data.length + 1); } // 插入元素方法 public void add(int index,String str){ // 判断索引是否越界 if (index < 0 || index > size) throw new IndexOutOfBoundsException("数组越界了"); // 判断是否需要扩容 if (size >= data.length){ grow(); } // 插入元素其实就是将数据向后挪动一位,然后腾出来的那一位赋值为要插入的数据 // 方式一: // for (int i = size - 1;i >= index;i--){ // data[i + 1] = data[i]; // } // 方式二: System.arraycopy(data,index,data,index + 1,size - index); data[index] = str; // 实际元素+1 size++; } /** * 删除指定索引处的元素 * @param index */ public void remove(int index){ // 判断索引是否越界 out(index); // 删除元素就是将后面的元素依次向前移动一位 // 方式一: // for (int i = index;i < size - 1;i++){ // data[i] = data[i + 1]; // } // 方式二: System.arraycopy(data,index + 1, data,index,size - index - 1); // 实际元素个数-1 size--; } private void out(int index) { if (index >= size || index < 0) throw new IndexOutOfBoundsException(); } /** * 查找指定元素首次出现的索引,找不到返回-1 */ public int indexOf(String str){ for (int i = 0; i < size; i++) { // if (str == data[i] || str != null && str.equals(data[i])){ // return i; // } if (Objects.equals(str,data[i])){ return i; } } return -1; } /** * 删除指定元素 */ public void remove(String str){ // 查找str首次出现的位置 int index = indexOf(str); if (index != -1) remove(index); } /** * 清空集合 */ public void clear(){ data = new String[10]; size = 0; } /** * 判断是否包含某个元素 */ public boolean contains(String str){ return indexOf(str) != -1; } /** * 获取指定索引处的元素 */ public String get(int index){ // 判断是否越界 out(index); return data[index]; } /** * 判断集合是否为空 */ public boolean isEmpty(){ return size == 0; } /** * 替换元素 */ public void set(int index,String str){ out(index); data[index] = str; } /** * 获取元素个数 */ public int size(){ return size; } /** * 截取子列表 * @return */ public ArrayListDemo sublist(int fromIndex,int toIndex){ // 判断索引是否越界 out(fromIndex); out(toIndex); // 判断参数是否合法 if (fromIndex > toIndex) throw new IllegalArgumentException(); // 创建新的列表 ArrayListDemo sublist = new ArrayListDemo(toIndex - fromIndex); // 拷贝数据 System.arraycopy(data,fromIndex,sublist.data,0,toIndex - fromIndex); // 设置实际元素个数 sublist.size = toIndex - fromIndex; return sublist; } // [元素1, 元素2, 元素3] @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("["); for (int i = 0; i < size; i++) { if (i != size - 1){ stringBuilder.append(data[i]).append(", "); }else { stringBuilder.append(data[i]); } } stringBuilder.append("]"); return stringBuilder.toString(); } }
1.3.5 LinkedList的特点
底层数据结构是双向链表
内存是不连续的
增删速度快
查询速度慢
异步线程不安全的集合
1.3.6 实现LinkedList
package cn.javasm.demo; import java.util.Objects; public class LinkedListDemo { /** * 实际元素个数 */ private int size; /** * 头结点 */ private Node first; /** * 尾结点 */ private Node last; // 结点 private class Node{ // 数据 String item; // 上一个结点 Node prev; // 下一个结点 Node next; public Node(String item, Node prev, Node next) { this.item = item; this.prev = prev; this.next = next; } } /** * 添加元素 * @param str 数据 */ public void add(String str){ // 创建新结点 Node node = new Node(str,null,null); // 添加元素分为两种情况 // 1.添加的是第一个结点 要求头尾相同 if (size == 0){ this.first = node; }else { // 2.不是第一个结点 this.last.next = node; node.prev = this.last; } this.last = node; size++; } /** * 插入元素 * @param index 插入的索引 * @param str 数据 */ public void add(int index,String str){ // 判断索引是否越界 if (index > size || index < 0) throw new IndexOutOfBoundsException(); // 插入元素分为三种情况 // 1.插入到尾部 2.插入到中间 3.插入到头部 // 插入到尾部就是添加元素 if (index == size){ add(str); return; } // 创建新结点 Node node = new Node(str,null,null); if (index == 0){// 插入到头部 node.next = this.first; this.first.prev = node; this.first = node; }else { // 插入到中间 // 先查询要插入索引的元素 Node no = getNode(index); no.prev.next = node; node.prev = no.prev; node.next = no; no.prev = node; } size++; } /** * 根据索引查找结点 * @param index * @return */ private Node getNode(int index) { Node no = first; for (int i = 0; i < index; i++) { no = no.next; } return no; } /** * 删除指定索引处的元素 * @param index */ public void remove(int index){ // 判断索引是否越界 out(index); // 删除元素分为: 1.删除头结点 2.删除尾结点 3.删除中间结点 if (index == 0){// 删除头结点 this.first = this.first.next; this.first.prev = null; }else if (index == size - 1){//删除尾结点 this.last = this.last.prev; this.last.next = null; }else {// 删除中间结点 Node node = getNode(index); node.prev.next = node.next; node.next.prev = node.prev; } size--; } private void out(int index) { if (index >= size || index < 0) throw new IndexOutOfBoundsException(); } /** * 查询指定元素首次出现的索引 * @param str 指定的元素 * @return 索引 */ public int indexOf(String str){ // 获取头结点 Node node = this.first; for (int i = 0; i < size; i++) { if (Objects.equals(str,node.item)){ return i; } node = node.next; } return -1; } /** * 删除指定元素的结点 */ public void remove(String str){ // 查找出现的索引 int index = indexOf(str); if (index != -1) this.remove(index); } /** * 清空链表 */ public void clear(){ this.first = this.last = null; size = 0; } /** * 判断是否包含指定的元素 * @return */ public boolean contains(String str){ return indexOf(str) != -1; } /** * 获取元素 * @return */ public String get(int index){ //判断是否越界 out(index); return getNode(index).item; } /** * 判断链表是否为空 * @return */ public boolean isEmpty(){ return size == 0; } /** * 替换元素 * @return */ public void set(int index,String str){ // 判断是否越界 out(index); getNode(index).item = str; } /** * 获取元素个数 * @return */ public int size(){ return size; } /** * 截取子链表 */ public LinkedListDemo sublist(int fromIndex,int toIndex){ // 判断是否越界 out(fromIndex); out(toIndex); // 判断参数是否合法 if (fromIndex > toIndex) throw new IllegalArgumentException(); // 创建新链表 LinkedListDemo sublist = new LinkedListDemo(); // 获取开始的结点 Node node = getNode(fromIndex); for (int i = fromIndex;i < toIndex;i++){ sublist.add(node.item); node = node.next; } return sublist; } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("["); Node node = this.first; for (int i = 0; i < size; i++) { if (i != size - 1){ stringBuilder.append(node.item).append(", "); }else { stringBuilder.append(node.item); } node = node.next; } stringBuilder.append("]"); return stringBuilder.toString(); } public Node getFirst() { return first; } public Node getLast() { return last; } }