1. 程式人生 > >迭代器的應用和集合進階List&Set

迭代器的應用和集合進階List&Set

集合進階

迭代器

Iterable:可迭代的。
1. 為什麼要有Iterable:每種集合,底層資料結構不同,取出方式不同,為了能以統一的一種方式取出所有集合的元素,定義迭代器。
2. 為什麼Iterable是一個介面:介面的抽象方法,是一個標準,其實現類必須實現。保證所有的實現類實現了自己特有的迭代方法。
3. 為什麼Iterable不做成一個抽象類:因為介面是多實現的,而抽象類是單繼承的。
4. Iterable:它的所有的實現類都是可以被迭代輸出的。

List<String> list = new ArrayList<String>();
list.add("one"
); list.add("two"); list.add("three"); list.add("four"); list.add("five"); // Iterable的抽象方法返回Iterator Iterator<String> it = list.iterator();// 迭代器 while(it.hasNext()){// one two three four five System.out.println(it.next()); }

5. Iterator相當於一個游標,開始指向開始的地方,當迭代器迭代一次之後,游標指向最後一個值,不能二次迭代。

List<String> list = new
ArrayList<String>(); list.add("one"); list.add("two"); list.add("three"); list.add("four"); list.add("five"); Iterator<String> it = list.iterator(); while(it.hasNext()){// one two three four five String str = it.next(); System.out.print(it.next()); } while(it.hasNext()){// 無輸出 String str = it.next(); System.out.println("2:"
+str); }

6. ListIterator
ConcurrentModificationException:併發修改異常
在使用迭代器迭代的過程中,如果使用list增加、刪除或修改元素,則會報併發修改異常。

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
Iterator<String> it = list.iterator();
while(it.hasNext()){
    String str = it.next();
    if(str.equals("one")){
// ConcurrentModificationException
        list.add("list");
    }
}
System.out.println(list);

Iterator的子介面:ListIterator,專門用於List集合,提供了add和remove方法解決迭代過程中併發修改異常。

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");

ListIterator<String> it = list.listIterator();
while(it.hasNext()){
    String str = it.next();
    if(str.equals("one")){
        it.add("list");
    }
}
// [one, list, two, three, four, five]
System.out.println(list);

ListIterator還提供了逆序迭代:

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");

// 逆序迭代輸出
ListIterator<String> it = list.listIterator(list.size());
while(it.hasPrevious()){// five four three two one 
    String str = it.previous();
    System.out.println(str);
}

迭代器的簡化應用——foreach的使用

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
// one two three four five 
for(String str :list){
    System.out.println(str);
}

List&Set

1. List&Set
List:

  • 元素存入順序和取出順序一致(有序)
  • 元素可以重複
  • 可以使用get(i)的方式將元素取出
  • List中刪除、查詢、判斷是否包含依據是equals()方法

Set:hash(雜湊,雜湊)演算法 底層HashMap

  • 元素存入順序和取出順序不一致(無序),注意無序不是隨機順序
  • 元素會自動去重,不可以重複
  • 沒有get方法用於取出單個元素
  • HashSet中去重依據的是hashCode()方法和equals()方法
  • TreeSet:底層是二叉樹

2. ArrayList和LinkedList的區別?
ArrayList、Vector、LinkedList都是List集合。

  • ArrayList和Vector底層是陣列,而LinkedList底層是雙向連結串列。最多使用的是ArrayList
  • 陣列:新增元素非常耗時,查詢元素比較快。
  • 連結串列:查詢耗時,新增元素比較快。
  • 底層結構的不同決定了使用場景的不同

3. HashSet
在HashSet新增元素的過程中,先比較元素的hashCode()方法,如果hashCode()不同,則認為是兩個物件,則儲存
如果hashCode()相同,則比較equals()方法,如果equals()不同,則認為是兩個物件,則儲存
如果hashCode()相同equals()也相同,則認為是同一個物件,則不儲存

  • Java官方規定,重寫equals,必須重寫hashCode
  • 如果兩個物件的equals相等,則他們的hashCode一定相等,反之不成立。
  • hashCode equals toString :Object的三大重寫

4. TreeSet
set的特點:

  • 元素存入順序和取出順序不一致
  • 會自動將元素按照字典順序進行排序
  • 排序依據的是compareTo方法
  • 物件想要放入TreeSet中,需要具有可比較性。如何具有可比較性?

    • 1、類實現Comparable介面,提供comparTo方法,方法中定義排序的規則。 這裡的方法返回值int:如果等於0,則認為是同一個物件,如果大於0,則排後面,如果小於0,在排前面。
    • 2、在TreeSet中提供一個Comparator比較器的實現類,重寫compare方法。優先選擇本方案,比較靈活,可以使用在多個比較的場景。
  • 牛刀小試

public class Person implements Comparable<Person>{
    private String name;
    private int age;
    ......
    @Override
    public int compareTo(Person o) {// 重寫comparTo方法定義比較規則
        if(this.getAge() != o.getAge()){
            return this.getAge()-o.getAge();// 年齡從小到大,主碼
        }else {
            return this.getName().compareTo(o.getName());//名字的字典順序
        }
    }

// 測試類中程式碼
Set<Person> set = new TreeSet<Person>();
Person p1 = new Person("zhangsan",20);
Person p2 = new Person("lisi",18);
Person p3 = new Person("wangwu",20);
Person p4 = new Person("zhaoliu",19);
Person p5 = new Person("tianqi",20);
Person p6 = new Person("zhangsan",20);

set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p5);
set.add(p6);

for (Person person : set) {
    System.out.println(person);
}
//Person [name=lisi, age=18]
//Person [name=zhaoliu, age=19]
//Person [name=tianqi, age=20]
//Person [name=wangwu, age=20]
//Person [name=zhangsan, age=20]