學(xué)習(xí)集合之前復(fù)習(xí)相關(guān)知識:
Hash:翻譯為散列米母、哈希勾扭,所以散列和哈希指的是同一個概念。
散列碼:一種標(biāo)識碼铁瞒,由散列碼算法確定妙色。
“散列碼”就是用來把一堆對象散到各自的隊(duì)列里去的一種標(biāo)識碼。
舉個形象一點(diǎn)的例子慧耍,一年有 365 天身辨,從 1 編號到 365,下面我定義一種編碼方法芍碧,每個人按照他生日那天的編號作為他的標(biāo)識碼煌珊,這樣,一群人每個人就會有一個標(biāo)識碼泌豆。
這個標(biāo)識碼有什么用呢定庵?好,下面我說踪危,請所有單號的人站到一起蔬浙,所有雙號的人站在一起。此后,當(dāng)我要找一個人的時候,如果知道他的編號是單號逼裆,那我只需要到前面一堆人里去找,查找效率提高了一倍绎晃。
如果我說蜜唾,請編號能被 16 整除的人站到一起,被 16 除余 1 的人站到一起庶艾,被 16 除余 2 的人站到一起…… 此后,當(dāng)我要找一個人的時候擎勘,查找效率就會提高到 16 倍咱揍。
這就是散列碼。所以棚饵,一個好的散列碼算法煤裙,配合一個適當(dāng)?shù)拇鎯C(jī)制,就能夠?qū)崿F(xiàn)高效的存儲管理噪漾。
那么硼砰,不好的散列碼算法會有多糟糕呢?比如欣硼,hashCode() 返回一個常量题翰,那么,無論什么存儲機(jī)制都會退化诈胜,所有的人都站在一堆里豹障,查找效率無法提高。不過焦匈,也就只是影響效率血公,不會影響“正確性”,因?yàn)樯⒘写a的本性決定了缓熟,所有的算法都不應(yīng)該假設(shè)兩個不同的對象必須有不同的散列碼累魔。
- 哈希表(也叫散列表):
- 結(jié)合了數(shù)組和鏈表的優(yōu)勢,其實(shí)就是一種特殊的數(shù)據(jù)結(jié)構(gòu)
- 哈希表有多種不同的實(shí)現(xiàn)方法
-
紅黑樹
- 之前學(xué)習(xí)過二叉樹够滑,紅黑樹也是一種樹形的數(shù)據(jù)結(jié)構(gòu)
看一下Object類中定義的方法
toString()方法:
- 返回對象的字符串表示形式垦写,可以自己書寫返回的格式(類型是字符串)
equals()方法和雙等號:
- equals:進(jìn)行值的比較
- ==:進(jìn)行值和引用對象的地址是否一致
hashCode()方法:
- 返回對象的哈希碼值
/** *This method is supported for the benefit of hash tables such as those *provided by java.util.HashMap *支持此方法是為了哈希表的優(yōu)勢,例如由HahMap提供的哈希表 **/
- Java中
HashCode()
方法就是根據(jù)一定的規(guī)則將于對象相關(guān)的信息(比如對象的存儲地址版述、對象的字段等)映射成一個值梯澜,這個數(shù)值就是哈希碼值(也叫散列碼值)
-
Comparable接口:
- 內(nèi)部比較器,實(shí)現(xiàn)了此接口的類可與自身對象進(jìn)行比較渴析,依賴于CompareTo()方法的實(shí)現(xiàn)晚伙,CompareTo()方法有三個返回值
- Comparable和Comparator區(qū)別
一、類集
1俭茧、集合的作用
集合和對象數(shù)組類似咆疗,都是保存對象的容器。但是集合更加強(qiáng)大母债,提供了添加午磁、遍歷尝抖、排序和刪除等一系列基本操作,且集合可以動態(tài)擴(kuò)容迅皇。
在實(shí)際開發(fā)中昧辽,大多數(shù)情況下數(shù)據(jù)的測定依賴于對象的傳遞,只有極少數(shù)是在操作具體的數(shù)據(jù)(聯(lián)系DAO開發(fā)模式)
2登颓、操作單值對象的集合-Collection家裝
- 以下的實(shí)現(xiàn)類不是直接實(shí)現(xiàn)接口的搅荞,省略了一部分抽象類(Map家族也是)、
- Collection家族是對單值進(jìn)行操作的集合
3框咙、操作二元偶對象的集合-Map家族
- 存儲結(jié)構(gòu)是key-value鍵值對咕痛,不像Collection是單列集合
- 必須知道什么是散列表和紅黑樹
二、Collection接口
- Collection接口提供了一系列操作集合的方法
1喇嘱、Collection有兩大子接口
-
List:
- 有序茉贡,元素可重復(fù)
- 允許為null
-
Set:
- 無序,不可重復(fù)
- 底層大多是Map結(jié)構(gòu)的實(shí)現(xiàn)
- 常用的三個實(shí)現(xiàn)類(HashSet、TreeSet者铜、LinkedHashSet)都是線程非同步
- Collection的使用必須依賴于兩大子接口的實(shí)現(xiàn)類
三腔丧、List接口
- List接口繼承了Collection接口
1、常用的實(shí)現(xiàn)類
ArrayList
:①可調(diào)整大小的數(shù)組的實(shí)現(xiàn)②非線程安全③采用異步處理王暗,性能更優(yōu)
Vector
:①用法與ArrayList
相似②線程安全③采用同步處理方式悔据,性能較低
LinkedList
:實(shí)現(xiàn)鏈表結(jié)構(gòu),即實(shí)現(xiàn)了List
接口又實(shí)現(xiàn)了Queue
接口
(1)俗壹、ArrayList
- ArrayList是數(shù)組結(jié)構(gòu)
package com.alexanderbai.collection.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
/**
* @Author AlexanderBai
* @data 2019/3/26 17:00
*/
class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(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) {//覆寫equals方法
if (this == o){ //判斷地址是否相等
return true;
}
if (!(o instanceof Person)) {//判斷是否屬于同一類對象
return false;
}
/*上面的代碼等價于
if (o == null || this.getClass() != o.getClass()) {
return false;
}
*/
Person person = (Person) o;
return Objects.equals(name, person.name) &&//依次進(jìn)行屬性比較
Objects.equals(age, person.age);
/*上面的代碼等價于
if (this.name.equals(person.name) && this.age == person.age) {
return true;
} else {
return false;
}
*/
}
@Override
public int hashCode() {//覆寫hashCode()的方法
return this.name.hashCode() * this.age;//計算公式
}
@Override
public String toString() {
return "姓名:"+this.name +";年齡:"+this.age;
}
@Override
public int compareTo(Person person) {//覆寫comparTo()方法科汗,指定排序規(guī)則
if (this.age>person.age) {
return 1;
}
if (this.age < person.age) {
return -1;
}
return this.name.compareTo(person.name); //增加字符串的比較
}
}
public class TestList {
public static void main(String[] args) {
List<String> listString = new ArrayList<>();
//1、添加類庫元素
listString.add("Hello");
listString.add("World!!");
System.out.println("listString = " + listString);
listString.remove("hello");
System.out.println("listString = " + listString);
//2绷雏、添加自定義元素
List<Person> personList = new ArrayList<>();
personList.add(new Person());
personList.add(new Person("AlexanderBai",20));
personList.add(new Person("Alexander",21));
System.out.println("personList = " + personList);
System.out.println("-------------------------------------------------------");
personList.remove(new Person());
//3头滔、輸出
//第一種輸出,集合的標(biāo)準(zhǔn)輸出
Iterator<Person> iterator=personList.iterator();
while (iterator.hasNext()) {
Person person=iterator.next();
System.out.println(person.toString());
}
System.out.println("-------------------------------------------------------");
//forEach輸出
for (Person person: personList) {
System.out.println(person.toString());
}
System.out.println("-------------------------------------------------------");
//簡單佛如循環(huán)
for (int i = 0; i <(personList.size()); i++) {
System.out.println("personList.get("+i+") = " + personList.get(i));
}
}
}
(2)涎显、Vector
- 用法與ArrayList相似
public class TestList {
public static void main(String[] args) {
List<String> list= new Vector<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
Iterator<String> iterator=list.iterator();
while (iterator.hasNext()) {
String string = iterator.next();
System.out.println(string);
}
}
}
(3)坤检、LinkedList
- LinkedList是鏈表結(jié)構(gòu),實(shí)現(xiàn)了Queue(隊(duì)列)接口
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
- 常用方法如下:
add() | addAll(Collection<? extends E) | addAll(int ,Collection<? extends E) |
---|---|---|
addFirst()/addLast() | get() | remove()/removeFirst()/removeLast() |
pop()/push() | peek() | poll()/pollFirst()/pollLast() |
package com.alexanderbai.collection.list;
import java.util.*;
/**
* @Author AlexanderBai
* @data 2019/3/26 17:00
*/
class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
}
public Person(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) {//覆寫equals方法
if (this == o){ //判斷地址是否相等
return true;
}
if (!(o instanceof Person)) {//判斷是否屬于同一類對象
return false;
}
/*上面的代碼等價于
if (o == null || this.getClass() != o.getClass()) {
return false;
}
*/
Person person = (Person) o;
return Objects.equals(name, person.name) &&//依次進(jìn)行屬性比較
Objects.equals(age, person.age);
/*上面的代碼等價于
if (this.name.equals(person.name) && this.age == person.age) {
return true;
} else {
return false;
}
*/
}
@Override
public int hashCode() {//覆寫hashCode()的方法
return this.name.hashCode() * this.age;//計算公式
}
@Override
public String toString() {
return "姓名:"+this.name +";年齡:"+this.age;
}
@Override
public int compareTo(Person person) {//覆寫comparTo()方法,指定排序規(guī)則
if (this.age>person.age) {
return 1;
}
if (this.age < person.age) {
return -1;
}
return this.name.compareTo(person.name); //增加字符串的比較
}
}
public class TestList {
public static void main(String[] args) {
List<Person> linkedList = new LinkedList<>();
linkedList.add(new Person());
linkedList.add(new Person("張三", 21));
linkedList.add(new Person("李四", 22));
linkedList.add(new Person("王五", 20));
linkedList.add(new Person("趙六", 19));
System.out.println("linkedList.get(2) = " + linkedList.get(2));
System.out.println("((LinkedList<Person>) linkedList).peek() = " + ((LinkedList<Person>) linkedList).peek());//Retrieves(取出), but does not remove, the head (first element) of this list.
System.out.println(linkedList);
System.out.println("((LinkedList<Person>) linkedList).getFirst() = " + ((LinkedList<Person>) linkedList).getFirst());
System.out.println("((LinkedList<Person>) linkedList).getFirst() = " + ((LinkedList<Person>) linkedList).getFirst());
System.out.println("((LinkedList<Person>) linkedList).peekFirst() = " + ((LinkedList<Person>) linkedList).peekFirst());
System.out.println(linkedList);
((LinkedList<Person>) linkedList).addFirst(new Person("新來的", 22));
System.out.println(linkedList);
System.out.println("((LinkedList<Person>) linkedList).peekLast() = " + ((LinkedList<Person>) linkedList).peekLast());
Iterator<Person> iterator=linkedList.iterator();
System.out.println("以先進(jìn)先出的方式輸出:");
while (iterator.hasNext()) {
Person person = iterator.next();
System.out.println(person.toString());
}
}
}
四期吓、Set接口
- Set接口繼承了Collection接口
1早歇、常用的實(shí)現(xiàn)類
- HashSet:
- 底層數(shù)據(jù)結(jié)構(gòu)是哈希表(是一個元素為鏈表的數(shù)組)+紅黑樹
- 實(shí)際上是封裝了HashMap
- 元素?zé)o序,允許為null
TreeSet
- 底層數(shù)據(jù)結(jié)構(gòu)實(shí)際上是一個TreeMap的實(shí)例(紅黑樹)
- 可以實(shí)現(xiàn)排序功能
- 元素不能為空
- LinkedHashSet
- 底層數(shù)據(jù)結(jié)構(gòu)實(shí)際上是一個哈希表(是一個元素為鏈表的數(shù)組)+雙向鏈表
- 實(shí)際上是LinkHashMap
- 允許元素為空
五讨勤、SortedSet接口
1箭跳、認(rèn)識Sorted接口
public interface SortedSet<E> extends Set<E> ================================================================================== public class TreeSet<E> extends AbstractSet<E>
稱為Java排序集-在元素上具有順序的集合
-
實(shí)現(xiàn)Sorted中元素的有序有兩種方式:
- 實(shí)現(xiàn)Comparable接口,使用CompareTo方法來排序元素(如JDK中的String類已經(jīng)實(shí)現(xiàn)了Comparable接口潭千,所以可以添加到Sorted集合中)谱姓,稱為自然排序。
- 實(shí)現(xiàn)Comparator接口刨晴,重寫compare方法屉来,使之符合自己的需求
- Comparable和Comparator區(qū)別
package com.alexanderbai.collection.set; import java.util.SortedSet; import java.util.TreeSet; /** * @Author AlexanderBai * @data 2019/3/27 16:23 */ public class TestSet { public static void main(String[] args) { SortedSet<String> stringSortedSet = new TreeSet<>(); stringSortedSet.add("java"); stringSortedSet.add("MySQL"); stringSortedSet.add("css"); stringSortedSet.add("html"); System.out.println(stringSortedSet); } }
- 運(yùn)行結(jié)果有序:
[MySQL, css, html, java]
2路翻、指定年齡和姓名同時進(jìn)行比較
-
年齡和姓名都相同時不會重復(fù)添加到集合
package com.alexanderbai.collection.set; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; /** * @Author AlexanderBai * @data 2019/3/27 16:23 */ public class TestSet { public static void main(String[] args) { SortedSet<Person> personSortedSet = new TreeSet<>(); personSortedSet.add(new Person("AlexanderBai", 20)); personSortedSet.add(new Person("alexanderbai", 20)); personSortedSet.add(new Person("alexanderbai", 21)); personSortedSet.add(new Person("alexander", 21)); personSortedSet.add(new Person("alexander", 21)); System.out.println(personSortedSet); } } class Person implements Comparable<Person>{ private String name; private int age; public Person() { } public Person(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) {//覆寫equals方法 if (this == o){ //判斷地址是否相等 return true; } if (!(o instanceof Person)) {//判斷是否屬于同一類對象 return false; } /*上面的代碼等價于 if (o == null || this.getClass() != o.getClass()) { return false; } */ Person person = (Person) o; return Objects.equals(name, person.name) &&//依次進(jìn)行屬性比較 Objects.equals(age, person.age); /*上面的代碼等價于 if (this.name.equals(person.name) && this.age == person.age) { return true; } else { return false; } */ } @Override public int hashCode() {//覆寫hashCode()的方法 return this.name.hashCode() * this.age;//計算公式 } @Override public String toString() { return "姓名:"+this.name +";年齡:"+this.age+"\n"; } @Override public int compareTo(Person person) {//覆寫comparTo()方法,指定排序規(guī)則 if (this.age>person.age) { return 1; } if (this.age < person.age) { return -1; } return this.name.compareTo(person.name); //增加字符串的比較 } }
- 運(yùn)行結(jié)果:
[姓名:AlexanderBai;年齡:20 , 姓名:alexanderbai;年齡:20 , 姓名:alexander;年齡:21 , 姓名:alexanderbai;年齡:21 ]
3茄靠、指定年齡進(jìn)行比較
-
年齡相同的不會重復(fù)被添加到集合
package com.alexanderbai.collection.set; import java.util.Comparator; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; /** * @Author AlexanderBai * @data 2019/3/27 16:23 */ public class TestSet { public static void main(String[] args) { SortedSet<Person> personSortedSet = new TreeSet<>(Comparator.comparing(Person::getAge)); personSortedSet.add(new Person("AlexanderBai", 20)); personSortedSet.add(new Person("alexanderbai", 20)); personSortedSet.add(new Person("alexanderbai", 21)); personSortedSet.add(new Person("alexander", 21)); System.out.println(personSortedSet); } } class Person{ private String name; private int age; public Person() { } public Person(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) {//覆寫equals方法 if (this == o){ //判斷地址是否相等 return true; } if (!(o instanceof Person)) {//判斷是否屬于同一類對象 return false; } /*上面的代碼等價于 if (o == null || this.getClass() != o.getClass()) { return false; } */ Person person = (Person) o; return Objects.equals(name, person.name) &&//依次進(jìn)行屬性比較 Objects.equals(age, person.age); /*上面的代碼等價于 if (this.name.equals(person.name) && this.age == person.age) { return true; } else { return false; } */ } @Override public int hashCode() {//覆寫hashCode()的方法 return this.name.hashCode() * this.age;//計算公式 } @Override public String toString() { return "姓名:"+this.name +";年齡:"+this.age+"\n"; } }
- 運(yùn)行結(jié)果:
[姓名:AlexanderBai;年齡:20 , 姓名:alexanderbai;年齡:21 ]
4茂契、指定姓名進(jìn)行比較
-
姓名相同的不會重復(fù)添加到集合中
package com.alexanderbai.collection.set; import java.util.Comparator; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; /** * @Author AlexanderBai * @data 2019/3/27 16:23 */ public class TestSet { public static void main(String[] args) { SortedSet<Person> personSortedSet = new TreeSet<>(Comparator.comparing(Person::getName)); personSortedSet.add(new Person("AlexanderBai", 20)); personSortedSet.add(new Person("alexanderbai", 20)); personSortedSet.add(new Person("alexanderbai", 21)); personSortedSet.add(new Person("alexander", 21)); System.out.println(personSortedSet); } } class Person{ private String name; private int age; public Person() { } public Person(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) {//覆寫equals方法 if (this == o){ //判斷地址是否相等 return true; } if (!(o instanceof Person)) {//判斷是否屬于同一類對象 return false; } /*上面的代碼等價于 if (o == null || this.getClass() != o.getClass()) { return false; } */ Person person = (Person) o; return Objects.equals(name, person.name) &&//依次進(jìn)行屬性比較 Objects.equals(age, person.age); /*上面的代碼等價于 if (this.name.equals(person.name) && this.age == person.age) { return true; } else { return false; } */ } @Override public int hashCode() {//覆寫hashCode()的方法 return this.name.hashCode() * this.age;//計算公式 } @Override public String toString() { return "姓名:"+this.name +";年齡:"+this.age+"\n"; } }
-
運(yùn)行結(jié)果:
[姓名:AlexanderBai;年齡:20 , 姓名:alexander;年齡:21 , 姓名:alexanderbai;年齡:20 ]
-
六、集合的輸出
1慨绳、Iterator迭代輸出
Iterator只能進(jìn)行單向的遍歷账嚎,調(diào)用iterator()方法是注意類型轉(zhuǎn)換
Iterator<String> iterator=list.iterator();
2、雙向迭代輸出
- 使用ListIterator進(jìn)行由后往前迭代輸出時必須先進(jìn)行由前向后的輸出操作
public class TestList {
public static void main(String[] args) {
List<String> list= new Vector<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
ListIterator<String> listIterator=list.listIterator();
System.out.println("由前向后輸出:");
while (listIterator.hasNext()) {
String string = listIterator.next();
System.out.println(string);
}
System.out.println("由后往前輸出:");
while (listIterator.hasPrevious()) {
String string = ((ListIterator<String>) listIterator).previous();
System.out.println(string);
}
}
}
3儡蔓、foreach輸出
集合也支持foreach和簡單for循環(huán)的輸出(見List接口的實(shí)現(xiàn)類ArrayList的輸出操作)
七、Map接口
實(shí)際上Map不是一個集合疼邀,而是一個集合<key>到另一個集合<value>的映射喂江,即Entry<key,value>.
-
Entry是一個Map中的接口,用來存儲實(shí)際的數(shù)據(jù)旁振,當(dāng)我們調(diào)用Map的put()方法來存儲數(shù)據(jù)获询,其實(shí)是把數(shù)據(jù)放入Entry中。
interface Entry<K,V>
1拐袜、Map常用的實(shí)現(xiàn)類
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable
public interface NavigableMap<K,V> extends SortedMap<K,V>
public interface SortedMap<K,V> extends Map<K,V>
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable
(1)吉嚣、HashMap
無序存放,key不允許重復(fù)蹬铺,允許為null
-
與之類似的還有HashTable(也是Map的實(shí)現(xiàn)類)尝哆,已過時
package com.alexanderbai.map; import java.util.*; /** * @Author AlexanderBai * @data 2019/3/28 8:52 */ public class TestMap { public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); map.put(1,"AlexanderBai" ); map.put(2, "xiaobai"); map.put(3, "dalao"); System.out.print("通過key獲取value值:"); System.out.println("map.get(2) = " + map.get(2)); System.out.print("以set集合的方式返回map集合:"); System.out.println(map.entrySet()); System.out.print("判斷是否含有指定的key:"); if (map.containsKey(3)) { System.out.println("key=3,value=" + map.get(3)); } else { System.out.println("搜索的key不存在"); } System.out.print("判斷是否含有指定的value值:"); if (map.containsValue("boss")) { System.out.println("搜索的value存在"); } else { System.out.println("搜索的value不存在"); } System.out.println("以set的方式返回所有的key,并輸出全部的key"); Set<Integer> keys=map.keySet(); Iterator<Integer> integerIterator=keys.iterator(); while (integerIterator.hasNext()) { System.out.print(integerIterator.next()+"甜攀、"); } System.out.println(); System.out.println("以Collection的方式返回value秋泄,并輸出全部的value"); Collection<String> values=map.values(); Iterator<String> iterator=values.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next()+"、"); } System.out.println(); System.out.println("輸出map集合:"); Set<Integer> keys1=map.keySet(); Iterator<Integer> integerIterator1=keys.iterator(); while (integerIterator1.hasNext()) { Integer integer=integerIterator1.next(); System.out.println("key="+integer+",value="+map.get(integer)); } } }
運(yùn)行結(jié)果
通過key獲取value值:map.get(2) = xiaobai 以set集合的方式返回map集合:[1=AlexanderBai, 2=xiaobai, 3=dalao] 判斷是否含有指定的key:key=3,value=dalao 判斷是否含有指定的value值:搜索的value不存在 以set的方式返回所有的key规阀,并輸出全部的key 1恒序、2、3谁撼、 以Collection的方式返回value歧胁,并輸出全部的value AlexanderBai、xiaobai厉碟、dalao喊巍、 輸出map集合: key=1,value=AlexanderBai key=2,value=xiaobai key=3,value=dalao
(2)、TreeMap
-
實(shí)現(xiàn)了Sorted接口墨榄,屬于可以排序的集合玄糟,按集合中的key進(jìn)行排序,元素不允許重復(fù)
package com.alexanderbai.map; import java.util.*; /** * @Author AlexanderBai * @data 2019/3/28 8:52 */ class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.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 String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class TestMap { public static void main(String[] args) { Map<Integer, String> map = new TreeMap<>(); map.put(2, "AlexanderBai"); map.put(1, "xiaobai"); map.put(0, "boss"); System.out.println(((TreeMap<Integer, String>) map).firstKey()); System.out.println(((TreeMap<Integer, String>) map).lastKey()); System.out.println(((TreeMap<Integer, String>) map).firstEntry()); System.out.println(((TreeMap<Integer, String>) map).lastEntry()); Set<Integer> integerSet = map.keySet(); Iterator<Integer> integerIterator = integerSet.iterator(); while (integerIterator.hasNext()) { Integer integer = integerIterator.next(); System.out.println("key=" + integer + ",value=" + map.get(integer)); } Map<String, Person> map1 = new TreeMap<>(); map1.put("B", new Person("AlexanderBai",20)); map1.put("C", new Person("xiaobai", 18)); map1.put("A", new Person("boss", 38)); System.out.println(((TreeMap<String, Person>) map1).firstKey()); System.out.println(((TreeMap<String, Person>) map1).lastKey()); System.out.println(((TreeMap<String , Person>) map1).firstEntry()); System.out.println(((TreeMap<String, Person>) map1).lastEntry()); Set<String> stringSet = map1.keySet(); Iterator<String> stringIterator =stringSet.iterator(); while (stringIterator.hasNext()) { String str= stringIterator.next(); System.out.println("key=" + str + ",value=" + map1.get(str)); } } }
-
運(yùn)行結(jié)果
0 2 0=boss 2=AlexanderBai key=0,value=boss key=1,value=xiaobai key=2,value=AlexanderBai A C A=Person{name='boss', age=38} C=Person{name='xiaobai', age=18} key=A,value=Person{name='boss', age=38} key=B,value=Person{name='AlexanderBai', age=20} key=C,value=Person{name='xiaobai', age=18}
從運(yùn)行結(jié)果可以看出袄秩,TreeMap實(shí)現(xiàn)了Map集合元素的排序阵翎,上述以key作為排序?qū)ο?/p>
(3)逢并、LinkedHashMap
允許為null,插入有序
是HashMap的子類
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
大多使用HashMap的API郭卫,只不過重寫了部分方法砍聊,所以用法與HashMap類似
-
簡單來說就是Map集合的哈希表和鏈表(包括雙向鏈表)的實(shí)現(xiàn)
public class TestMap { public static void main(String[] args) { Map<Integer, String> map = new LinkedHashMap<>(); map.put(1, "boss"); map.put(2, "xiaobai"); map.put(3, "AlexanderBai"); System.out.print("通過key獲取value值:"); System.out.println("map.get(2) = " + map.get(2)); System.out.print("以set集合的方式返回map集合:"); System.out.println(map.entrySet()); System.out.print("判斷是否含有指定的key:"); if (map.containsKey(3)) { System.out.println("key=3,value=" + map.get(3)); } else { System.out.println("搜索的key不存在"); } System.out.print("判斷是否含有指定的value值:"); if (map.containsValue("boss")) { System.out.println("搜索的value存在"); } else { System.out.println("搜索的value不存在"); } System.out.println("以set的方式返回所有的key,并輸出全部的key"); Set<Integer> keys=map.keySet(); Iterator<Integer> integerIterator=keys.iterator(); while (integerIterator.hasNext()) { System.out.print(integerIterator.next()+"贰军、"); } System.out.println(); System.out.println("以Collection的方式返回value玻蝌,并輸出全部的value"); Collection<String> values=map.values(); Iterator<String> iterator=values.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next()+"、"); } System.out.println(); System.out.println("輸出map集合:"); Set<Integer> keys1=map.keySet(); Iterator<Integer> integerIterator1=keys.iterator(); while (integerIterator1.hasNext()) { Integer integer=integerIterator1.next(); System.out.println("key="+integer+",value="+map.get(integer)); } } }
(4)词疼、ConcurrentHashMap
- key和value都不能為空
- 一般用于高并發(fā)和大數(shù)統(tǒng)計
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> map = new ConcurrentHashMap<>();
map.put(1, "c");
map.put(2, "b");
map.put(3, "a");
map.put(6, "boss");
map.put(5, "xiaobai");
map.put(4, "AlexanderBai");
System.out.print("通過key獲取value值:");
System.out.println("map.get(2) = " + map.get(2));
System.out.print("以set集合的方式返回map集合:");
System.out.println(map.entrySet());
System.out.print("判斷是否含有指定的key:");
if (map.containsKey(3)) {
System.out.println("key=3,value=" + map.get(3));
} else {
System.out.println("搜索的key不存在");
}
System.out.print("判斷是否含有指定的value值:");
if (map.containsValue("boss")) {
System.out.println("搜索的value存在");
} else {
System.out.println("搜索的value不存在");
}
System.out.println("以set的方式返回所有的key俯树,并輸出全部的key");
Set<Integer> keys=map.keySet();
Iterator<Integer> integerIterator=keys.iterator();
while (integerIterator.hasNext()) {
System.out.print(integerIterator.next()+"、");
}
System.out.println();
System.out.println("以Collection的方式返回value贰盗,并輸出全部的value");
Collection<String> values=map.values();
Iterator<String> iterator=values.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next()+"许饿、");
}
System.out.println();
System.out.println("輸出map集合:");
Set<Integer> keys1=map.keySet();
Iterator<Integer> integerIterator1=keys.iterator();
while (integerIterator1.hasNext()) {
Integer integer=integerIterator1.next();
System.out.println("key="+integer+",value="+map.get(integer));
}
}
}
八、SortedMap接口
public interface SortedMap<K,V> extends Map<K,V>
- SortedMap是Map的直接子類舵盈,是要于排序的接口陋率,實(shí)現(xiàn)此接口的子類都屬于排序的子類,如:TreeMap
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable
public interface NavigableMap<K,V> extends SortedMap<K,V>
- TreeMap是SortedMap的實(shí)現(xiàn)類秽晚,SortedMap的使用見TreeMap的使用方法
- 同時也可以類比SortedSet的使用
九瓦糟、其他集合類
數(shù)組ArrayList
|
鏈表LinkedList
|
---|---|
棧Stack
|
隊(duì)列Queue
|
- ArrayList:可調(diào)整大小的數(shù)組的實(shí)現(xiàn)
- LinkedList:雙鏈表,即實(shí)現(xiàn)了List接口又實(shí)現(xiàn)了Queue接口
- Stack:堆棧的實(shí)現(xiàn)類
- Queue:隊(duì)列的實(shí)現(xiàn)類
1赴蝇、Stack類
- 棧:一種元素先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)菩浙,其中元素可以是基本數(shù)據(jù)類型,也可以是引用類型
- 棧的繼承關(guān)系:
- 棧的常用方法:
package com.alexanderbai.collection.set; import java.util.Stack; /** * @Author AlexanderBai * @data 2019/3/27 17:17 */ public class TestStack { public static void main(String[] args) { Stack<String> stringStack=new Stack<>(); stringStack.add("B"); stringStack.add("f"); stringStack.add("A"); stringStack.add("c"); stringStack.add("b"); System.out.println("stringStack.empty() = " + stringStack.empty()); System.out.println("stringStack = " + stringStack); System.out.println("stringStack.peek() = " + stringStack.peek()); System.out.println("stringStack = " + stringStack); System.out.println("stringStack.pop() = " + stringStack.pop()); System.out.println("stringStack = " + stringStack); System.out.println("stringStack.lastElement() = " + stringStack.lastElement()); System.out.print("新增元素:"); stringStack.addElement("AlexanderBai"); System.out.println("stringStack = " + stringStack); System.out.println("stringStack.contains(\"Alexander\") = " + stringStack.contains("Alexander")); System.out.print("清空棧"); stringStack.removeAllElements(); System.out.println("stringStack = " + stringStack); } }
- 運(yùn)行結(jié)果:
stringStack.empty() = false stringStack = [B, f, A, c, b] stringStack.peek() = b stringStack = [B, f, A, c, b] stringStack.pop() = b stringStack = [B, f, A, c] stringStack.lastElement() = c 新增元素:stringStack = [B, f, A, c, AlexanderBai] stringStack.contains("Alexander") = false 清空棧stringStack = []
2扯再、Queue類
- 隊(duì)列:一種元素先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)芍耘,其中元素可以是基本數(shù)據(jù)類型,也可以是引用類型
public interface Queue<E> extends Collection<E>
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
- Queue的實(shí)現(xiàn)類有
LinkedList
熄阻,使用方法見LinkedList
3斋竞、屬性類Properties
Properties一般用于配置文件,以key-value的結(jié)構(gòu)存儲
如常用的有關(guān)
jdbc
連接數(shù)據(jù)庫的配置
(1)秃殉、獲取JVM屬性
package com.alexanderbai.collection;
import java.util.Properties;
/**
* @Author AlexanderBai
* @data 2019/3/25 21:51
*/
public class PropertiesFileReadTest {
public static void main(String[] args) {
Properties properties=System.getProperties();
properties.list(System.out);
}
}
getProperties()方法說明:
- 此方法用于獲取JVM的系統(tǒng)屬性
list的說明:將屬性以指定流的形式打影映酢(上面是在控制臺打印)
(2)钾军、讀取任意的配置文件
package com.alexanderbai.collection;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/**
* 讀取和類在同一包下的屬性文件
* @Author AlexanderBai
* @data 2019/3/25 21:51
*/
public class PropertiesFileReadTest {
public static void main(String[] args) {
Properties properties = new Properties();
InputStream inputStream=null;
//此方法配置文件和類必須再同一包想
inputStream=PropertiesFileReadTest.class.getResourceAsStream("test.properties");
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
Enumeration propertyNames=properties.propertyNames();
while (propertyNames.hasMoreElements()) {
String key= (String) propertyNames.nextElement();
String value=properties.getProperty(key);
System.out.println( key +"="+value);
}
}
}
(3)鳄袍、讀取有關(guān)jdbc的配置屬性
- 下面兩個文件都在
com.alexanderbai.dbutil
包下- dbConfig.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/scott userName=root password=ROOT
- DBConnectionUtil.java
package com.alexanderbai.dbutil; import java.io.IOException; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * @Author AlexanderBai * @data 2019/3/26 0:07 */ public class DBConnectionUtil { public Connection openConnection() { Properties properties = new Properties(); String driver = null; String url = null; String userName = null; String password = null; try { properties.load( this.getClass().getResourceAsStream("dbConfig.properties") ); } catch (IOException e) { e.printStackTrace(); } driver = properties.getProperty("driver"); url = properties.getProperty("url"); userName= properties.getProperty("userName"); password= properties.getProperty("password"); try { Class.forName(driver); return DriverManager.getConnection(url, userName, password); } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { DBConnectionUtil dbConnectionUtil = new DBConnectionUtil(); System.out.println("dbConnectionUtil.openConnection() = " + dbConnectionUtil.openConnection()); } }
十、后言
以上只是java中集合框架的最基礎(chǔ)部分吏恭,隨著學(xué)習(xí)的深入拗小,應(yīng)該進(jìn)一步學(xué)習(xí)java集合框架的源碼實(shí)現(xiàn),只有弄明白源碼樱哼,才能真正領(lǐng)悟java類集的聯(lián)系與區(qū)別哀九。*
十一剿配、Demo
1、一對多關(guān)系
以學(xué)生和所在的學(xué)校為例阅束,一名學(xué)生只能在一個學(xué)校呼胚,而一個學(xué)校考研包含多個學(xué)生息裸。
-
School.java
package com.alexanderbai.demo; import java.util.ArrayList; import java.util.List; /** * @Author AlexanderBai * @data 2019/3/28 11:48 */ public class School { private String name; private List<Student> studentList = null; public School() { this.studentList=new ArrayList<>(); } public School(String name) { this();//調(diào)用無參構(gòu)造函數(shù) this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; } @Override public String toString() { return "學(xué)校名稱:" + this.name; } }
-
Student.java
package com.alexanderbai.demo; /** * @Author AlexanderBai * @data 2019/3/28 11:44 */ public class Student { private Integer id; private String name; private School school; public Student(Integer id, String name) { this.id = id; this.name = name; this.school = school; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public School getSchool() { return school; } public void setSchool(School school) { this.school = school; } @Override public String toString() { return "學(xué)號:" + this.id + ",姓名" + this.name; } }
-
Test.java
package com.alexanderbai.demo; import java.util.Iterator; /** * @Author AlexanderBai * @data 2019/3/28 11:54 */ public class Test { public static void main(String[] args) { School school = new School("牛逼大學(xué)"); Student student1 = new Student(1, "AlexanderBai"); Student student2 = new Student(2, "dalao"); Student student3 = new Student(3, "xiaobai"); //把學(xué)生加入到學(xué)校中(放入list集合)蝇更,list是school類的屬性 school.getStudentList().add(student1); school.getStudentList().add(student2); school.getStudentList().add(student3); //給學(xué)生確定所在的學(xué)校 student1.setSchool(school); student2.setSchool(school); student3.setSchool(school); System.out.println(school); Iterator<Student> iterable=school.getStudentList().iterator(); while (iterable.hasNext()) { System.out.println("\t|-" + iterable.next()); } } }
-
運(yùn)行結(jié)果:
學(xué)校名稱:牛逼大學(xué) |-學(xué)號:1,姓名AlexanderBai |-學(xué)號:2,姓名dalao |-學(xué)號:3,姓名xiaobai
2、多對多關(guān)系
以學(xué)生和所選課程為例呼盆,一名學(xué)生可以選多門課程年扩,一門課程可以有多個學(xué)生選課。
-
Student.java
package com.alexanderbai.demo; import java.util.ArrayList; import java.util.List; /** * @Author AlexanderBai * @data 2019/3/28 11:44 */ public class Student { private Integer id; private String name; private List<Course> list = null; private School school; public Student() { this.list = new ArrayList<>(); } public Student(Integer id, String name) { this(); this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public School getSchool() { return school; } public void setSchool(School school) { this.school = school; } public List<Course> getList() { return list; } public void setList(List<Course> list) { this.list = list; } @Override public String toString() { return "學(xué)號:" + this.id + ",姓名" + this.name; } }
-
School.java
package com.alexanderbai.demo; import java.util.ArrayList; import java.util.List; /** * @Author AlexanderBai * @data 2019/3/28 11:48 */ public class School { private String name; private List<Student> studentList = null; private List<Course> courseList = null; public School() { this.studentList=new ArrayList<>(); this.courseList = new ArrayList<>(); } public School(String name) { this();//調(diào)用無參構(gòu)造函數(shù) this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; } public List<Course> getCourseList() { return courseList; } public void setCourseList(List<Course> courseList) { this.courseList = courseList; } @Override public String toString() { return "學(xué)校名稱:" + this.name; } }
-
Courese.java
package com.alexanderbai.demo; import java.util.ArrayList; import java.util.List; /** * @Author AlexanderBai * @data 2019/3/28 12:15 */ public class Course { private Integer No; private String name; private List<Student> list = null; public Course() { this.list = new ArrayList<>(); } public Course(Integer no, String name) { this(); No = no; this.name = name; } public Integer getNo() { return No; } public void setNo(Integer no) { No = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getList() { return list; } public void setList(List<Student> list) { this.list = list; } @Override public String toString() { return "課程編號:" + this.No + ",課程名稱:" + this.name; } }
-
Test.java
package com.alexanderbai.demo; import java.util.Iterator; /** * @Author AlexanderBai * @data 2019/3/28 11:54 */ public class Test { public static void main(String[] args) { School school = new School("牛逼大學(xué)"); Student student1 = new Student(1, "AlexanderBai"); Student student2 = new Student(2, "dalao"); Student student3 = new Student(3, "xiaobai"); Course course1 = new Course(1, "java"); Course course2 = new Course(2, "JavaEE"); Course course3 = new Course(3, "數(shù)據(jù)庫原理及應(yīng)用"); //把學(xué)生加入到學(xué)校中(放入list集合)访圃,list是school類的屬性 school.getStudentList().add(student1); school.getStudentList().add(student2); school.getStudentList().add(student3); //給學(xué)生確定所在的學(xué)校 student1.setSchool(school); student2.setSchool(school); student3.setSchool(school); school.getCourseList().add(course1); school.getCourseList().add(course2); school.getCourseList().add(course3); //-------------------------------模擬學(xué)生選課---------------------------------- //向課程類添加學(xué)生 course1.getList().add(student1); course1.getList().add(student3); course2.getList().add(student1); course2.getList().add(student2); course3.getList().add(student2); course3.getList().add(student3); //向?qū)W生類添加課程 student1.getList().add(course1); student1.getList().add(course3); student2.getList().add(course1); student2.getList().add(course2); student3.getList().add(course2); student3.getList().add(course3); System.out.println(school); Iterator<Student> iterable=school.getStudentList().iterator(); while (iterable.hasNext()) { Student student=iterable.next(); System.out.println("\t|-" +student); Iterator<Course> courseIterator=student.getList().iterator(); while (courseIterator.hasNext()) { System.out.println("\t\t|-" + courseIterator.next()); } } System.out.println(school); Iterator<Course> courseIterator1= school.getCourseList().iterator(); while (courseIterator1.hasNext()) { Course course=courseIterator1.next(); System.out.println("\t|-" +course); } } }
-
運(yùn)行結(jié)果:
學(xué)校名稱:牛逼大學(xué) |-學(xué)號:1,姓名AlexanderBai |-課程編號:1,課程名稱:java |-課程編號:3,課程名稱:數(shù)據(jù)庫原理及應(yīng)用 |-學(xué)號:2,姓名dalao |-課程編號:1,課程名稱:java |-課程編號:2,課程名稱:JavaEE |-學(xué)號:3,姓名xiaobai |-課程編號:2,課程名稱:JavaEE |-課程編號:3,課程名稱:數(shù)據(jù)庫原理及應(yīng)用 學(xué)校名稱:牛逼大學(xué) |-課程編號:1,課程名稱:java |-課程編號:2,課程名稱:JavaEE |-課程編號:3,課程名稱:數(shù)據(jù)庫原理及應(yīng)用