集合的結構圖
集合框架
List集合面試兩大陷阱:
1.用for循環一邊遍歷一邊刪除
刪除不乾淨:一邊遍歷一邊刪除,集合角標每次再自增1,而每次刪除一個元素後集合下標和大小size會改變,所以只可以刪除一半的元素
2.數組轉換集合
Arrays.asList–返回值是Arrays類的一個靜態內部類,而這個內部類不支持增加和修改,只能支持查看和修改
Vector是同步的,線程安全
ArrayList是異步的,線程不安全
Collection是List和Set的父接口
Collections是集合的工具類
*集合中存儲的都是對象的地址
Collection分爲兩大類:List和Set
List:元素是有序的,元素可以重複,因爲該集合體繫有下標
Set:元素是無序的,元素不可以重複,因爲該集合體系沒有下標
①List又包含三種類型的數據存儲容器:ArrayList、 LinkedList 和Vector
–ArrayList:底層的數據結構使用的是數組結構,線程不同步,默認長度大小爲10,當不夠用時每次增長度的50%。
特點:查詢 速度很快,但是增刪稍慢
–LinkedList:底層使用的鏈表數據結構。特點:增刪速度很快,查詢慢
–Vector:底層使用的也是數組數據結構,線程同步。默認長度大小爲10,當不夠用時每次增長度的100%。 被ArrayList替代了
Set包含兩種數據存儲容器類型:HashSet和TreeSet
②List集合特有的迭代器。ListIterator是Iterator的子接口。在迭代時,不可以通過集合對象的方法操作集合中的元素,會發生ConcurrentModificationException異常。所以,在使用迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的。只有三個方法:hasNext( )判斷是否存在下一個元素、next( )取下一個元素、remove( )移除元素引用的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator,該接口中有許多Iterator接口中不存在的方法,且該接口只能通過List集合的listIterator方法獲取
Set下面的集合:
一、TreeSet(即排序,又查重):
① 比較器的實現
查重標準:比較器接口中自己定義規則
set集合中的自定義對象都要實現比較器接口Comparable(),覆寫裏面的compareTo()方法。
如果放入set集合中的類型無法在其本類中實現比較器接口,那麼要通過第三方類實現比較的功能,則在此第三方類中實現Comparator接口,並覆寫其中的compare()方法,則此時在TreeSet的參數裏面傳入實現Comparator接口的類對象
compareTo()和compare()方法中當前類對象的某個屬性大於另外一個對象的相同屬性是,return 1,如果小於的話return -1;如果相同的話return 0
實現代碼例子:
package TreeSet;
import java.util.Comparator;
public class Person {
String name;
int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
if(this.age > o.age){
return 1;
}
if(this.age < o.age){
return -1;
}
return this.name.compareTo(o.name);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.name + " " + this.age;
}
}
二、HashSet(只查重,不排序)
hashCode是定義在Object中的方法,根據對象的地址動態計算出一個值
如果set集合中的放入的是引用數據類型,則查重標準爲:
①hashCode: 首先調用hashCode方法進行HashCode值的比較。也就是==比較,因爲hashCode方法就是和地址有關
所以調用父類的hashCode方法沒有意義,需要覆寫
②equals:如果兩個對象hashCode值一樣,調用equals,比較的是地址,所以也無意義,因爲比較地址就是比較hashCode的值。所以要對equals方法進行覆寫
總而言之,當兩個對象的hashCode值相同時,就調用equals方法再進行各項屬性之間的比較。如果hashCode值不同時,則就不再需要進行equals比較。
代碼例子:
package HashSet;
public class Person {
String name;
int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
int x1 = age*31;
int x2 = name.length()*78;
return x1*x2;
}
@Override
public boolean equals(Object obj) {
Person p = (Person) obj;
boolean flag1 = name.equals(p.name);
boolean flag2 = age==p.age;
return flag1 && flag2;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.name + " " + this.age;
}
}
Map下面的集合:(Map中鍵都不允許重複)
Map分爲hashMap和TreeMap
一、TreeMap(鍵不允許爲空,值可以爲空)
treeMap中鍵不允許重複
在自定義對象類中實現比較器接口Comparable或着在第三方類中實現Comparable接口,覆寫其中的comparaTo()方法進行查重和比較
二、hashMap(鍵和值都可以爲空null)
hashMap只可以實現查重,不可以實現排序,它和HashSet一樣,都是通過類對象覆寫hashCode()和equals()方法來實現通過具體的屬性進行查重。
Hashtable:底層是哈希表數據結構,不可以存入null鍵、null值。該集合時線程同步的
HashMap:底層是哈希表數據結構,允許使用bull值和null鍵,該集合是不同步的
map集合的兩種取出方式:
Map集合的取出原理:將map集合轉成set集合,再通過迭代器取出。
1.keyset:返回類型是Set。將map中的所有的鍵存入到Set集合。因爲set具備迭代器,所以可以用迭代器方式取出所有的鍵,再根據get方法,獲取每一個鍵對應的值
2.entrySet:返回類型是Set
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("06", "java06");
map.put("03", "java03");
Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
String value = map.get(key);
System.out.println("Key:" + key + " Value:" + value);
}
}
entrySet圖例:
entrySet代碼樣例:
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("05", "java05");
map.put("02", "java02");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry<String, String> me = it.next();
String key = me.getKey();
String value = me.getValue();
System.out.println("key:" + key + " value:" + value);
}
}
Entry<K, V>是一個接口,是Map<K, V>接口中的內部接口,是用static修飾符所修飾的靜態內部接口,用來存放映射項(鍵-值對)
TreeSet、HashSet、TreeMap和HashMap的代碼實現:
主函數類:
public class Test {
/**
* HashMap只可以查重,不可以排序
* 和HashSet一樣,都是需要覆寫hashCode和equals方法進行查重
*/
public static void main(String[] args) {
HashMap<String,Person> map = new HashMap<>();
map.put("xx2", new Person("張三2",18));
map.put("xx1", new Person("張三1",12));
map.put("xx5", new Person("張三5",13));
map.put("xx1", new Person("張三1",15));
map.put("xx7", new Person("張三7",16));
map.put("xx6", new Person("張三7",16));
map.put("xx3", new Person("張三3",14));
Set<String> key = map.keySet();
Iterator<String> it = key.iterator();
while(it.hasNext()){
String k = it.next();
Person p = map.get(k);
System.out.println("鍵:" + k + " 學生:" + p);
}
}
/**
* TreeMap:可以查重和排序
* 在將數據放入集合中以後可以通過Set集合將map集合中的鍵存入set集合中
* 用的是keySet方法,在通過Set的迭代器將鍵的和遍歷
* 通過while循環取出鍵,再通過鍵在map集合中取出該鍵對應的值。
*/
public static void main3(String[] args) {
TreeMap<String,Person> map = new TreeMap<>();
map.put("xx2", new Person("張三2",18));
map.put("xx1", new Person("張三1",12));
map.put("xx5", new Person("張三5",13));
map.put("xx1", new Person("張三1",15));
map.put("xx7", new Person("張三7",16));
map.put("xx6", new Person("張三7",16));
map.put("xx3", new Person("張三3",14));
Set<String> key = map.keySet();
Iterator<String> it = key.iterator();
while(it.hasNext()){
String k = it.next();
Person p = map.get(k);
System.out.println("鍵:" + k + " 學生:" + p);
}
}
/**
* HashSet集合中只可以進行查重,不可以進行排序。
*/
public static void main2(String[] args) {
HashSet<Person> set = new HashSet<>();
set.add(new Person("xx2",12));
set.add(new Person("xx6",16));
set.add(new Person("xx9",19));
set.add(new Person("xx3",13));
set.add(new Person("xx2",12));
set.add(new Person("xx1",11));
set.add(new Person("xx3",13));
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
/**
* TreeSet:Set集合含有迭代器,可以進行集合的遍歷
* 可以進行排序和查重
*/
public static void main1(String[] args) {
TreeSet<Person> set = new TreeSet<>();
set.add(new Person("xx2",12));
set.add(new Person("xx6",16));
set.add(new Person("xx9",19));
set.add(new Person("xx3",13));
set.add(new Person("xx2",12));
set.add(new Person("xx1",11));
set.add(new Person("xx3",13));
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
//對象類:
public class Person {
String name;
int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "name:" + name + " age:" + age;
}
// HashMap只可以查重,不可以排序
//通過覆寫hashCode和equals方法進行查重
@Override
public int hashCode() {
int x1 = name.length()*78;
int x2 = age*31;
return x1*x2;
}
@Override
public boolean equals(Object obj) {
Person per = (Person)obj;
boolean flag = this.name.equals(per.name);
boolean flag1 = this.age == per.age;
return flag && flag1;
}
//TreeMap:可以進行排序和查重,其中必須是鍵不相同,不同的鍵有相同的值是可以的
// 需要實現比較器接口
// implements Comparable<Person>
@Override
public int compareTo(Person o) {
if(this.age > o.age){
return 1;
}
if(this.age < o.age){
return -1;
}
else{
return this.name.compareTo(o.name);
}
}
// HashSet:只可以查重,不可以排序.
// 通過在對象類中覆寫hashCode()和equals()方法
// 先通過hashCode方法進行查重,不相同直接返回;
// 相同則執行equals方法進行查重
@Override
public int hashCode() {
int x1 = name.length()*78;
int x2 = age*31;
return x1*x2;
}
@Override
public boolean equals(Object obj) {
Person per = (Person)obj;
boolean flag = this.name.equals(per.name);
boolean flag1 = this.age == per.age;
return flag && flag1;
}
// TreeSet:可以排序,也可以查重,通過實現Comparable接口,
// 如果本類實現不了的話則選擇在第三方的類中實現Comparator接口
//implements Comparable<Person>
@Override
public int compareTo(Person o) {
if(this.age > o.age){
return 1;
}
if(this.age < o.age){
return -1;
}
else{
return this.name.compareTo(o.name);
}
}