一、數據結構
1.棧結構
特點:先進後出
棧內存:先進後出。主方法最先壓棧,剩餘的方法隨着調用就會不斷的進棧。當執行完畢時,立即從棧內存消失
堆內存:當new對象的時候,對象纔出現。當這個對象沒有任何引用的時候,會變成垃圾。由垃圾回收器不定時的回收
棧結構只能操作一端,不是運算受限的線性表
2.隊列結構
特點:先進先出
舉例:排隊
運算受限的線性表
能對首尾進行操作
LinkedList中的addFrist()和addLast()可以模擬出隊列
3.數組結構
特點:
查詢快:數組是一塊連續的內存空間。而且有對應的索引。通過索引快速的定位到要查找的內容
增刪慢:數組的長度是固定的,如果要對元素進行增刪。則需要創建新數組來完成
4.鏈表結構
數據結構層面特點:
查詢慢:鏈表的地址不是連續的,查詢的時候需要一個一個的進行查找
增刪快:每個元素都會記錄上一個元素的地址值(雙向的是互相記錄地址)。如果想刪除或增加一個元素,其他的元素不需要變動,只需要將對應的記錄更改即可
LinkedList集合:
此集合也是有索引的。有索引但是查詢慢的原因如下:
我們傳入一個要查詢的索引,底層先會做一個判斷。
結果1:如果傳入的索引要是比集合長度的中間值索引要小,從前向後查找。而且是一個一個的找
結果2:如果傳入的索引要是比集合長度的中間值索引要大,從後向前查找。而且是一個一個的找
總結:
如果查詢多,優先使用ArrayList
如果增刪多,優先使用LinkedList
如果不確定,優先使用ArrayList
5.樹結構
圖解略~
二、List
1.List特點
有索引、可以存儲重複元素、存取有序
ArrayList:底層是數組實現,查詢快、增刪慢。
|–ArrayList集合底層是數組結構,第一個數組是長度爲10,如果添加的元素超過10,那麼下一個就會
以1.5倍的速度去創建一個新的集合,再使用Arrays.copyOfRange(Object []original,start,end) 不包含end
/*
//這就屬於多態 只能用List接口裏面的方法
List<String> list = new ArrayList<>();
//欲想使用ArrayList集合中的trimToSzie()方法,那麼就不許轉型
// 這僅僅是爲了演示一下多態的轉型概念
ArrayList<String> arr = (ArrayList<String>) list;
arr.trimToSize(); //這時候就可以使用這個方法了
*/
LinkedList:底層是鏈表實現,查詢慢、增刪快。
|--可以對首尾進行操作(添加或者刪除操作)比add(int index,E element) 和 remove(int index)
方法的效率要稍微高那麼一點點,因爲他在進行添加刪除操作的時候不用去通過下標去查找
2.常用方法
void add(int index,E e); 向集合中指定索引位置去添加元素
E get(int index); 獲取指定索引處的元素
E remove(int index); 刪除指定索引上的元素
E set(int index,E e); 修改指定索引上的元素
3.示例代碼:
public class Demo01List {
public static void main(String[] args) {
//創建一個List集合對象,多態
List<String> list = new ArrayList<>();
//使用add方法往集合中添加元素
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");
//打印集合
System.out.println(list);//[a, b, c, d, a] 不是地址重寫了toString
//public void add(int index, E element): 將指定的元素,添加到該集合中的指定位置上。
//在c和d之間添加一個itheima
list.add(3,"itheima");//[a, b, c, itheima, d, a]
System.out.println(list);
//public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
//移除元素
String removeE = list.remove(2);
System.out.println("被移除的元素:"+removeE);//被移除的元素:c
System.out.println(list);//[a, b, itheima, d, a]
//public E set(int index, E element):用指定元素替換集合中指定位置的元素,返回值的更新前的元素。
//把最後一個a,替換爲A
String setE = list.set(4, "A");
System.out.println("被替換的元素:"+setE);//被替換的元素:a
System.out.println(list);//[a, b, itheima, d, A]
}
}
4.LinkedList集合
特有方法:
java.util.LinkedList集合 implements List接口
LinkedList集合的特點:
1.底層是一個鏈表結構:查詢慢,增刪快
2.裏邊包含了大量操作首尾元素的方法
注意:使用LinkedList集合特有的方法,不能使用多態
void addFirst(E e):將指定元素插入此列表的開頭。
void addLast(E e):將指定元素添加到此列表的結尾。
void push(E e):將元素推入此列表所表示的堆棧。
E getFirst():返回此列表的第一個元素。
E getLast():返回此列表的最後一個元素。
E removeFirst():移除並返回此列表的第一個元素。
E removeLast():移除並返回此列表的最後一個元素。
E pop():從此列表所表示的堆棧處彈出一個元素。
boolean isEmpty():如果列表不包含元素,則返回true。
public class Demo02LinkedList {
public static void main(String[] args) {
show03();
}
/*
- public E removeFirst():移除並返回此列表的第一個元素。
- public E removeLast():移除並返回此列表的最後一個元素。
- public E pop():從此列表所表示的堆棧處彈出一個元素。此方法相當於 removeFirst
*/
private static void show03() {
//創建LinkedList集合對象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);//[a, b, c]
//String first = linked.removeFirst();
String first = linked.pop();
System.out.println("被移除的第一個元素:"+first);
String last = linked.removeLast();
System.out.println("被移除的最後一個元素:"+last);
System.out.println(linked);//[b]
}
/*
- public E getFirst():返回此列表的第一個元素。
- public E getLast():返回此列表的最後一個元素。
*/
private static void show02() {
//創建LinkedList集合對象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
//linked.clear();//清空集合中的元素 在獲取集合中的元素會拋出NoSuchElementException
//public boolean isEmpty():如果列表不包含元素,則返回true。
if(!linked.isEmpty()){
String first = linked.getFirst();
System.out.println(first);//a
String last = linked.getLast();
System.out.println(last);//c
}
}
/*
- public void addFirst(E e):將指定元素插入此列表的開頭。
- public void addLast(E e):將指定元素添加到此列表的結尾。
- public void push(E e):將元素推入此列表所表示的堆棧。此方法等效於 addFirst(E)。
*/
private static void show01() {
//創建LinkedList集合對象
LinkedList<String> linked = new LinkedList<>();
//使用add方法往集合中添加元素
linked.add("a");
linked.add("b");
linked.add("c");
System.out.println(linked);//[a, b, c]
//public void addFirst(E e):將指定元素插入此列表的開頭。
//linked.addFirst("www");
linked.push("www");
System.out.println(linked);//[www, a, b, c]
//public void addLast(E e):將指定元素添加到此列表的結尾。此方法等效於 add()
linked.addLast("com");
System.out.println(linked);//[www, a, b, c, com]
}
}
5.Vector集合
ArrayList和Vector集合的區別
相同點:底層都是數組實現的
不同點:ArrayList是JDK1.2版本出現的。Vector是JDK1.0版本出現的
ArrayList是線程不安全的,效率較高,但是數據不安全
Vector是線程安全的,效率較低,但是數據安全
示例代碼:
public class Demo01 {
public static void main(String[] args) {
Vector<String> v = new Vector<>();
v.addElement("abc");
v.addElement("bcd");
v.addElement("def");
for (String s : v) {
System.out.println(s);
}
System.out.println("================");
Iterator<String> it = v.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
System.out.println("================");
Enumeration<String> e = v.elements();
while(e.hasMoreElements()) {
System.out.println(e.nextElement());
}
}
}
三、Set
1.Set集合特點
無索引、不能存儲重複元素、存取無序
HashSet:底層是哈希算法(紅黑樹),無索引、不能存儲重複元素、存取無序
LinkedHashSet:底層是哈希算法+鏈表雙實現,無索引、不能存儲重複元素。可以保證存取順序
|–LinkedHashSet是有序的
注意事項:
???Set集合遍歷的時候不能使用for循環(因爲沒有下標,無法對其遍歷)
|--增強for循環
|--迭代器
???紅黑樹(平衡二叉樹/排序樹)查詢速度相當快 -->桶結構存儲
2.示例代碼:
public class Demo01Set {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
//使用add方法往集合中添加元素
set.add(1);
set.add(3);
set.add(2);
set.add(1);
//使用迭代器遍歷set集合
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer n = it.next();
System.out.println(n);//1,2,3 無序,沒有重複的
}
//使用增強for遍歷set集合
System.out.println("-----------------");
for (Integer i : set) {
System.out.println(i);
}
}
}
3.Set集合不重複的原理
第一種情況:哈希值不同,直接存儲
第二種情況:哈希值相同,但是equals方法不同。以桶結構存儲
第三種情況:哈希值相同,但是equals方法也相同。不存儲了
4.HashSet存儲自定義類型數據
此類實現 Set 接口,由哈希表(實際上是一個 HashMap 實例)支持。
它不保證 set 的迭代順序;特別是它不保證該順序恆久不變。此類允許使用 null 元素。
//Person類
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//測試類
public class Demo03HashSetSavePerson {
public static void main(String[] args) {
//創建HashSet集合存儲Person
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("小美女",18);
Person p2 = new Person("小美女",18);
Person p3 = new Person("小美女",19);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);
}
}
5.LinkedHashSet集合的使用
public class Demo04LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set);//[abc, www, itcast] 無序,不允許重複
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcast");
System.out.println(linked);//[www, abc, itcast] 有序,不允許重複
}
}
四、可變參數
1.定義格式
數據類型…變量名
2.注意事項
一個方法的參數中只能有一個可變參數
如果有多個參數,可變參數必須放在最後一個
3.示例代碼
public class Demo01VarArgs {
public static void main(String[] args) {
//int i = add();
//int i = add(10);
int i = add(10,20);
//int i = add(10,20,30,40,50,60,70,80,90,100);
System.out.println(i);
method("abc",5.5,10,1,2,3,4);
}
/*
可變參數的注意事項
1.一個方法的參數列表,只能有一個可變參數
2.如果方法的參數有多個,那麼可變參數必須寫在參數列表的末尾
*/
/*public static void method(int...a,String...b){
}*/
/*public static void method(String b,double c,int d,int...a){
}*/
//可變參數的特殊(終極)寫法
public static void method(Object...obj){
}
/*
定義計算(0-n)整數和的方法
已知:計算整數的和,數據類型已經確定int
但是參數的個數不確定,不知道要計算幾個整數的和,就可以使用可變參數
add(); 就會創建一個長度爲0的數組, new int[0]
add(10); 就會創建一個長度爲1的數組,存儲傳遞來過的參數 new int[]{10};
add(10,20); 就會創建一個長度爲2的數組,存儲傳遞來過的參數 new int[]{10,20};
add(10,20,30,40,50,60,70,80,90,100); 就會創建一個長度爲2的數組,存儲傳遞來過的參數 new int[]{10,20,30,40,50,60,70,80,90,100};
*/
public static int add(int...arr){
//System.out.println(arr);//[I@2ac1fdc4 底層是一個數組
//System.out.println(arr.length);//0,1,2,10
//定義一個初始化的變量,記錄累加求和
int sum = 0;
//遍歷數組,獲取數組中的每一個元素
for (int i : arr) {
//累加求和
sum += i;
}
//把求和結果返回
return sum;
}
}
五、集合的工具類
1.Collections工具類
- public static boolean addAll(Collection c, T… elements):往集合中添加一些元素。
- public static void shuffle(List
public class Demo01Collections {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
Collections.addAll(list,"a","b","c","d","e");
System.out.println(list);//[a, b, c, d, e]
//public static void shuffle(List<?> list) 打亂順序:打亂集合順序。
Collections.shuffle(list);
System.out.println(list);//[b, d, c, a, e], [b, d, c, a, e]
}
}
- public static <T> void sort(List<T> list):將集合中元素按照默認規則排序。
示例代碼:
//Person類
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重寫排序的規則
@Override
public int compareTo(Person o) {
//return 0;//認爲元素都是相同的
//自定義比較的規則,比較兩個人的年齡(this,參數Person)
//return this.getAge() - o.getAge();//年齡升序排序
return o.getAge() - this.getAge();//年齡降序排序
}
}
//測試類
public class Demo02Sort {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
System.out.println(list01);//[1, 3, 2]
//public static <T> void sort(List<T> list):將集合中元素按照默認規則排序。
Collections.sort(list01);//默認是升序
System.out.println(list01);//[1, 2, 3]
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("c");
list02.add("b");
System.out.println(list02);//[a, c, b]
Collections.sort(list02);
System.out.println(list02);//[a, b, c]
ArrayList<Person> list03 = new ArrayList<>();
list03.add(new Person("張三",18));
list03.add(new Person("李四",20));
list03.add(new Person("王五",15));
System.out.println(list03);//[Person{name='張三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]
Collections.sort(list03);
System.out.println(list03);
}
}
- public static <T> void sort(List<T> list,Comparator<? super T> ):將集合中元素按照指定規則排序。
示例代碼:
//學生類
public class Student {
private String name;
private int age;
private int score;
public Student() {
}
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
//測試類
public class Test02 {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("張三",23,88);
Student s2 = new Student("李四",22,85);
Student s3 = new Student("王五",25,95);
Student s4 = new Student("趙六",22,87);
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
System.out.println(list);
//按照年齡的升序爲主要條件
//如果年齡一樣的情況,再按照成績的降序排序
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int result = s1.getAge() - s2.getAge(); // 按照年齡的升序排序
//如果年齡相同,再按照成績的降序排序
return (result == 0) ? s2.getScore() - s1.getScore() : result;
}
});
//按照年齡的升序排序
// [Student{name='李四', age=22, score=85}, Student{name='趙六', age=22, score=87}, Student{name='張三', age=23, score=88}, Student{name='王五', age=25, score=95}]
/*Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int result = s1.getAge() - s2.getAge();
return result;
}
});*/
System.out.println(list);
}
}
補充:
/*下面我想對一個ArrayList集合進行降序排序(本來默認的都是升序排序)*/
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(5);
list.add(3);
list.add(7);
list.add(4);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; //重寫之後的方法進行的是降序排序
}
});
System.out.println(list);
2.補充的工具類方法
public class Demo04 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
list.add("ee");
//int binarySearch(List list, T key) 使用二分查找法獲取元素在集合中出現的索引位置 如果查找的元素不存在,則返回此元素的-插入點-1
int index = Collections.binarySearch(list,"cc");
System.out.println(index);
//boolean replaceAll(List<T> list, T oldVal, T newVal) 使用新元素對集合中的老元素進行替換
Collections.replaceAll(list,"dd","kk");
System.out.println(list);
//void reverse(List<?> list) 反轉集合
Collections.reverse(list);
System.out.println(list);
//void swap(List<?> list, int i, int j) 將兩個索引位置上的元素交換
Collections.swap(list,0,1);
System.out.println(list);
//void copy(List dest, List src) 將源集合複製到目標集合中.目標集合長度必須大於等於源集合的長度
/* ArrayList<String> dest = new ArrayList<>();
dest.add("a");
dest.add("b");
dest.add("c");
dest.add("d");
dest.add("e");
dest.add("f");
Collections.copy(dest,list);
System.out.println(dest);*/
}
}