迭代器的应用和集合进阶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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值