集合
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);// 獲取指定元素首次出現的索引 找不到返回-1int index = list.indexOf("楊過");System.out.println(index);// 獲取指定元素最后一次出現的索引 找不到返回-1int 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(){// 默認長度是10data = 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));elsedata = 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;// 實際元素+1size++;} ?/*** 刪除指定索引處的元素* @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); ?// 實際元素個數-1size--;} ?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]@Overridepublic 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;} ?@Overridepublic 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;} } ?