一、數(shù)據(jù)結(jié)構(gòu)
1.1什么是數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)就是用來裝數(shù)據(jù)以及數(shù)據(jù)與之間關(guān)系的一種集合,如何把相關(guān)聯(lián)的數(shù)據(jù)存儲到計算機,為后續(xù)的分析提供有效的數(shù)據(jù)源,是數(shù)據(jù)結(jié)構(gòu)產(chǎn)生的由來。數(shù)據(jù)結(jié)構(gòu)就是計算機存儲、組織數(shù)據(jù)的方式。好的數(shù)據(jù)結(jié)構(gòu),讓我們做起事來事半功倍。精心選擇的數(shù)據(jù)結(jié)構(gòu)可以帶來更高的計算速度和存儲效率。
1.2常見的數(shù)據(jù)結(jié)構(gòu)
數(shù)組:操作數(shù)組利用下標(biāo),查詢快,但是增刪慢
鏈表:不依賴下標(biāo)每個鏈表環(huán)環(huán)相扣,增刪慢,查詢快
隊列:????????
樹形結(jié)構(gòu)
二、ArrayList
2.1ArrayList的介紹
內(nèi)部基于數(shù)組的集合類
ArrayList中有哪些方法:增加,刪除,修改,查詢,插入...
ArrayList的線程是不同步的。
?2.2ArrayList的使用
對它進行基本的增刪改查插入。
public static void main(String[] args) {
ArrayList list = new ArrayList();
ArrayList list01 = new ArrayList(list);
ArrayList list02 = new ArrayList(14);
list.add(1);
list.add("a");
list.add(true);
list.add(new Date());
list.add(1);
list.add(null);
//向指定下標(biāo)插入元素。
list.add(1,"xxx");
System.out.println(list);
list.remove(1);//刪除指定元素
//修改指定元素
list.set(0,9);
//查詢get
System.out.println(list.get(2));
System.out.println(list.size());
//集合有效長度。
}
?2.3遍歷方式
1普通for循環(huán)
2增強for循環(huán)
3使用迭代器進行遍歷
Iterator 就是一個迭代器(也是一個接口)其中的方法如下:
boolean hasNext() 判斷是否有下一個元素,如果返回true表示有下一個;
Object next() 調(diào)用一次獲得一個元素(每調(diào)用一次指針會向后移動一個);
void remove() 會從迭代器指向的結(jié)合容器中刪除一個元素
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.ListIterator;
public class LoopText {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(1);
list.add("a");
list.add(true);
list.add(new Date());
list.add(1);
list.add(null);
//向指定下標(biāo)插入元素。
list.add(1,"xxx");
//for遍歷集合
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("-------增強for------");
for (Object o : list) {
System.out.println(o);
}
System.out.println("---------第一次單項迭代器----------");
Iterator iterator = list.iterator();
//獲取迭代器
while (iterator.hasNext()){//判斷迭代器后面是否還有數(shù)據(jù)
System.out.println(iterator.next());//有數(shù)據(jù)就打印
}
System.out.println("------第二次迭代----------");
while (iterator.hasNext()){//判斷迭代器后面是否還有數(shù)據(jù)
System.out.println(iterator.next());
//第二次迭代沒有數(shù)據(jù)輸出因為迭代器的指針指向最后一位,后面沒有數(shù)據(jù)了
}
System.out.println("----------雙向迭代--------");
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.next());
}
System.out.println("----------------");
while (listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
}
}
雙向迭代器:單向迭代器有的功能雙向迭代器也有。不過它可以從數(shù)據(jù)的最后一位數(shù)往前迭代,原理與單項迭代器差不多,就是判斷前一個?元素,然后獲取上一個元素。
三、LinkedList
1、 內(nèi)部是基于鏈表結(jié)構(gòu)實現(xiàn)的。插入和刪除比較快,查詢相對ArrayList比較慢
2、 內(nèi)部相對于ArrayList而言多了一些操作頭和尾的方法
3、 可以充當(dāng)隊列,堆棧
4、 不是線程安全的(同步的)
四、HashSet
4.1HashSet的介紹
無序不可重復(fù),可存放null值 去重機制equals+hashcode 線程不安全 快速將一個集合元素去重
4.2驗證上面原則
打印上面示例中的元素的hashCode和equals的結(jié)果
2.嘗試自定義類,覆寫hashCode 和 equals 這兩個方法中的代碼隨便寫
(1) 嘗試修改兩個方法的值來測試容器中添加了幾個對象
創(chuàng)建一個user類
package org.lzh.set;
import java.util.Objects;
public class User implements Comparable{
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name) &&
Objects.equals(age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
User a = (User)o;
if(this.age>a.age){
return 1;
}else if(this.age < a.age){
return -1;
}else {
return this.name.compareTo(a.name);
}
}
}
//測試代碼
public class HashSetText {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
ArrayList arrayList = new ArrayList();
HashSet hashSet1 = new HashSet(arrayList);
hashSet.add(1);
hashSet.add("c");
hashSet.add(new Date());
hashSet.add(true);
hashSet.add(1);
hashSet.add(null);
hashSet.add(new User("za",14));
hashSet.add(new User("za",1));
System.out.println(hashSet);
//不能用普通for迭代
for (Object o : hashSet) {
System.out.println(o);
}
//迭代器,只能用單向迭代器
System.out.println("-------------------");
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
五、TreeSet
5.1TreeSet的介紹
無序:不保證(不記錄)我們的添加順序;但是排序了
2.不重復(fù):不能夠添加重復(fù)元素(多個心眼)如何判斷重復(fù)的呢?
3.感覺內(nèi)部存儲有一定的順序
**注意:TreeSet一旦添加了第一個元素后就不能添加其它數(shù)據(jù)類型的元素了,只能添加相同數(shù)據(jù)類型的元素,除非將容器中所有的元素全部清空,才能添加新的數(shù)據(jù)類型的元素
?5.2簡單體驗
*體驗1*:**不重復(fù)及不保證添加順序和打印順序一致
TreeSet ts = new TreeSet();
ts.add("B");
ts.add("A");
ts.add("C");
ts.add("C");
System.out.println(ts.size());
System.out.println(ts);
1.結(jié)果: 雖然打印結(jié)果的順序和添加順序可能不一致,但是**感覺結(jié)果是有某種規(guī)則排序的
2.說明String類也實現(xiàn)了Comparable接口,String對象可以調(diào)用compareTo方法
*體驗2*:**添加了一種類型不能在添加其他類型
TreeSet ts = new TreeSet();
ts.add("B");
ts.add("A");
ts.add("C");
ts.add("C");
ts.add(10);
System.out.println(ts.size());
System.out.println(ts);
---------------------------------------------
? ?Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at cn.itsource._07TreeSet.TestTreeSet.main(TestTreeSet.java:12)
1.結(jié)果:居然不能夠放不同的類型,但是編譯沒有錯
**體驗3: 添加自定義的類的對象 Student對象
TreeSet ts = new TreeSet();
Student stu1 = new Student("王者",18);
ts.add(stu1);
System.out.println(ts.size());
System.out.println(ts);
-----------------------------------------
? ?Exception in thread "main" java.lang.ClassCastException: cn.itsource._07TreeSet.Student cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at cn.itsource._07TreeSet.TestTreeSet.main(TestTreeSet.java:9)
1.結(jié)果:
2.疑問1:上面的代碼添加的都是同種類型的數(shù)據(jù),為什么還報錯;
3.疑問2:為什么提示要把Student轉(zhuǎn)成Comparable
4.正常情況 ----> TreeSet 或者 Comparable的文檔
5.3 TreeSet的結(jié)構(gòu)(存儲原理)分析
1.TreeSet內(nèi)部是按照大小進行排序的,大小有對象與對象之間比較進行決定的
2.設(shè)計TreeSet之前:Java設(shè)計了一個接口Comparable接口,其中提供了對象之間比較的方法CompareTo
3.TreeSet會調(diào)用對象的CompareTo方法,比較對象,所以我們放入的對象需實現(xiàn)Comparable
5.4 自然排序與定制排序(比較器)
5.4.1 自然排序 Comparable
**什么是自然排序
1.例如:大家排隊,按照高矮個排隊,那么同學(xué)們自己相互之間就能進行對比,每個對象具備自我比較判斷的能力,稱之為自然排序
*Comparable*中API**文檔中的描述:
2.此接口強行對實現(xiàn)它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的 compareTo 方法被稱為它的自然比較方法
**理解:
3.如果一個類實現(xiàn)了Comparable接口,可以認(rèn)為這個類的對象具有自然排序的能力(本質(zhì)就是這個對象可以調(diào)用比較的方法compareTo),這種比較和排序的規(guī)則就是自然排序
@Override
public int compareTo(Object o) {
if(o==null){
return 0;
}
Student stu = (Student)o;
if(this.age>stu.age){//如果大于的時候返回負(fù)數(shù)表示降序,返回負(fù)數(shù)表示升序
return -1;
}else if(this.age<stu.age){//如果大于的時候返回負(fù)數(shù)表示降序,返回負(fù)數(shù)表示升序
return 1;
}else{//如果年齡不大于也不小于說明等于,那么有名字來決定對象是否相同String已經(jīng)寫好排序規(guī)則
return this.name.compareTo(stu.name);
}
}
測試代碼
TreeSet ts = new TreeSet();
Student stu1 = new Student("XXX",20);
Student stu2 = new Student("XXX",20);
ts.add(stu1);
ts.add(stu2);
System.out.println(ts.size());
System.out.println(ts);
-------------------------------------
? ?1
[Student [name=XXX, age=20]]
**自然排序小結(jié)
5.4.2 定制排序(比較器)Comparator
1、什么是定制排序
定制排序,相當(dāng)于給容器提供了一個裁判:例如操場就是一個容器,那么體育老師就是這個裁判,每個同學(xué)進入操場同學(xué)們相互之間可以比較誰比較帥,或者不可以比較誰帥都可以,有了老師這個裁判,老師可以負(fù)責(zé)比較每一位同學(xué)
2、為什么需要定制排序
(1) 原來的比較規(guī)則不符合所有人的使用需求
(2) 不存在比較規(guī)則的對象,無法放入容器,我可以給容器提供定制比較器
3、定制排序如何實現(xiàn)
(1) Comparator 是一個比較器的接口(標(biāo)準(zhǔn)),必須得有進行比較的方法 :compare(Object o1,Object o2);
(2) 自定義一個類實現(xiàn)Comparator接口,其中寫比較規(guī)則 ---> 比較器的模板,我們現(xiàn)在需要的是一個具體的比較器對象
public class MyComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
if(o1==null||o2==null){//判斷,若兩個有一個為null都直接返回
return 0;
}
if(o1 instanceof Student && o2 instanceof Student){//如果類型匹配才轉(zhuǎn)換
Student stu1 = (Student)o1;
Student stu2 = (Student)o2;
if(stu1.age>stu2.age){//先判斷年齡后判斷姓名
return 1;
}else if(stu1.age<stu2.age){
return -1;
}else{
return stu1.name.compareTo(stu2.name);
}
}
return 0;
}
}
測試代碼
MyComparator mc = new MyComparator();
TreeSet ts = new TreeSet(mc);
Student stu1 = new Student("XXX",19);
Student stu2 = new Student("OOO",18);
Student stu3 = new Student("YYY",18);
Student stu4 = new Student("ZZZ",18);
Student stu5 = new Student("QQQ",18);
ts.add(stu1);
ts.add(stu2);
ts.add(stu3);
ts.add(stu4);
ts.add(stu5);
System.out.println(ts.size());
System.out.println(ts);
---------------------------------------
? ? 5
[OOO-18, QQQ-18, YYY-18, ZZZ-18, XXX-19]
7.5 TreeSet判斷重復(fù)的標(biāo)準(zhǔn)小結(jié)
1、如果采用的是自然排序調(diào)用對象的compareTo方法,如果返回0 表示相等;
大于且返回正數(shù),升序排列 => 小于且返回負(fù)數(shù),升序排列 對應(yīng)文章來源:http://www.zghlxwxcb.cn/news/detail-818231.html
大于且返回負(fù)數(shù),降序排列 => 小于且返回正數(shù),降序排列 對應(yīng)文章來源地址http://www.zghlxwxcb.cn/news/detail-818231.html
2、如果使用的定制排序(比較器),調(diào)用比較器的方法compare 返回0 表示相等;
大于且返回正數(shù),升序排列 => 小于且返回負(fù)數(shù),升序排列 對應(yīng)
大于且返回負(fù)數(shù),降序排列 => 小于且返回正數(shù),降序排列 對應(yīng)
到了這里,關(guān)于3.1集合-Set+集合-list的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!