Java集合--集合的遍历、Iterator、Predicate

数组的长度是不可变的,并且无法保存具有映射关系的数据。Java提供了集合,主要负责保存、盛装其他元素,因此,集合类也被称为容器类。

数组可以保存基本的数据类型和对象,集合只能保存对象。

Java类的集合主要由两个接口派生:Collection和Map。Collection的派生类Set和List代表无序集合和有序集合;Queue是Java的队列实现。

Map实现类用于保存具有映射关系的数据,每个保存的数据由key-value两个值组成。其中key是不可重复的。Set集合无法记住添加这个元素的顺序,所以Set集合不可重复;List集合非常像一个数组,可以记住每次添加元素的顺序,且List的长度可变。

如果访问List集合中的元素,可以根据元素的索引来访问;访问Map集合中的元素,可以根据key的值来访问;Set集合中的元素只能根据元素本身来访问

遍历集合方式:
方式一 Lambda表达式,这里是遍历集合
import java.util.Collection;
import java.util.HashSet;
/*
    Java的Iterator新增了一个forEach(Consumer action)方法,该方法所需参数的类型是一个函数式接口
    而Iterator接口是Collection的父接口,因此Collection可以直接调用该方法
    当调用Iterator的forEach方法时,程序会依次将集合元素传给Consumer的accept()方法
*/
public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new HashSet<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        c.forEach(obj -> System.out.println("迭代元素: " + obj));
    }
}

方式二 foreach遍历循环

import java.util.Collection;
import java.util.HashSet;
//foreach遍历循环
public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new HashSet<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        for(Object obj : c){
            System.out.println(obj);
        }
    }
}

方式三 Iterator方法

import java.util.HashSet;
import java.util.Iterator;
//foreach遍历循环
public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new HashSet<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        Iterator iter = c.iterator();
        while(iter.hasNext()){
            System.out.println(iter.next());
        }
    }
}

方式四 for循环

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
//for循环,这种方式仅对List有效,因为Set是无序的,不能用数组方式得到元素
public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new LinkedList<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        for(int i = 0; i < c.length; i++){
            System.out.println(c[i]);
        }
    }
}

Iterator主要用于迭代Collection集合中的元素,Iterator对象也被称为迭代器,使用iterator不可以改变元素本身,但是可以删除上一次next方法返回的对象

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;

public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new LinkedList<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        Iterator iter = c.iterator();
        while(iter.hasNext()){
            String str = (String)iter.next();
            if(str.equals("Lily")){
                iter.remove();
            }
            System.out.println(str);
        }
        //这里Lily已经被删除,但是在iterator的while循环中最后还是输出了Lily
        System.out.println(c);
    }
}

Iterator本身并不盛装对象,Iterator必须依附于Collection对象。当使用Iterator对集合元素进行迭代的时候,Iterator并不是把集合元素本身传给迭代变量,而是把集合元素的值传给迭代变量,所以修改迭代变量的值对集合元素本身没有任何影响。

Iterator迭代器采用的是快速失败(fail-fast)机制,一旦在迭代过程中检测到该集合已经被修改,程序会引发一场。迭代时删除会引发异常,只有在删除特定元素时,才不会引发异常。

对于HashSet以及ArrayList等,迭代时删除元素会引发异常,只有在删除集合中某个特定元素时才不会抛出异常。

迭代方式比较:

1、传统的for循环遍历,基于计数器的:

         顺序存储:读取性能比较高。适用于遍历顺序存储集合。
        链式存储:时间复杂度太大,不适用于遍历链式存储的集合。
2、迭代器遍历,Iterator:
        顺序存储:如果不是太在意时间,推荐选择此方式,毕竟代码更加简洁,也防止了Off-By-One的问题。
        链式存储:意义就重大了,平均时间复杂度降为O(n),还是挺诱人的,所以推荐此种遍历方式。
3、foreach循环遍历:
        foreach只是让代码更加简洁了,但是他有一些缺点,就是遍历过程中不能操作数据集合(删除等),所以有些场合不使用。而且它本身就是基于Iterator实现的,但是由于类型转换的问题,所以会比直接使用Iterator慢一点,但是还好,时间复杂度都是一样的。所以怎么选择,参考上面两种方式,做一个折中的选择。

Iterator的forEachRemaining方式迭代元素,这里是遍历迭代器Iterator

public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new LinkedList<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        Iterator iter = c.iterator();
        iter.forEachRemaining(obj -> System.out.println("迭代元素: " + obj));
    }
}

Java8中新增的的Predicate操作集合 removeIf(Predicate p)

public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new LinkedList<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        c.removeIf(ele -> ele.equals("Jim Green"));
        
        System.out.println(c);
    }
}

传入ele作为参数(集合的元素),删除满足条件的元素。

import java.util.function.Predicate;

public class CollectionClass{
    public static void main(String[] args){
        Collection<String> c = new LinkedList<String>();
        //添加元素
        c.add("lilei");
        c.add("hanmeimei");
        c.add("Jim Green");
        c.add("Lily");
        c.add("Lucy");
        
        //ele -> ((String)ele).contains("i") 判断条件,Lambda表达式写test()方式实现
        int i = callAll(c, ele -> ((String)ele).contains("i"));
        
        System.out.println(i);
    }
    
    public  static int callAll(Collection c, Predicate p){
        int total = 0;
        for(Object obj : c){
            //Predicate的test()方法判断该对象是否满足Predicate指定的条件
            if(p.test(obj)){
                total++;
            }
        }
        return total;
    }
}

 

猜你喜欢

转载自www.cnblogs.com/zaijie/p/11087601.html