java基础学习(十)容器-1

本文详细介绍了Java容器类库的基本概念及其使用方法,包括Collection、Map等主要接口,以及ArrayList、LinkedList、HashSet、TreeSet等具体实现类的特点与应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java容器类库的用途是保存对象,它提供两种不同的类型:
1、Collection。独立元素的序列。子类List必须按照插入的顺序保存元素;Set不能有重复的元素。
2、Map。一组成对的键值对对象。

在创建具体类的对象时,将其转型为对应的接口,然后在其余的代码中都使用这个接口,例如:

List<String> strList=new ArrayList<>();
List<String> strList2=new LinkedList<>();

但是LinkList具有在List中未包含的额外方法,如果想使用这些额外方法,那就不能将它们向上转型为更通用的接口。

实例,在Collection中填充Integer对象:

public static void main(String[] args) {
        //继承自Collection的类的对象都可以使用
        Collection<Integer> c=new ArrayList<Integer>();
        for(int i=0;i<10;i++){
            //在使用任何种类的List,不关心是否存在重复元素
            //而在Set中,只有元素不存在才会被添加
            c.add(i);
        }
        //遍历容器
        for(Integer i:c){
            System.out.println(i);
        }
    }

利用Arrays和Collection类中的实用方法,添加一组元素:

public static void main(String[] args) {
        //Arrays.asList()方法可以接受一个数组或者一个逗号分隔的元素列表(可变参数,元素个数不固定)
        Collection<Integer> collection=new ArrayList<Integer>(Arrays.asList(1,2,3));
        Integer[] moreInt=new Integer[]{5,6,7};
        //利用addAll()添加元素,只能接受另一个Collection类型
        collection.addAll(Arrays.asList(moreInt));
        for(Integer i:collection){
            System.out.print(i+" ");
        }
        //注意,上面的collection只能接受Collection对象,这样不灵活
        //可以使用Collections.addAll()方法,可以接受Collection对象,
        //以及使用一个数组  或者  用逗号分隔的元素列表(可变参数)
        //但是不能三者都放在一起,且必须有一个Collection对象,因为要将元素填充到collection中
        Collections.addAll(collection,9,8);
        Collections.addAll(collection,moreInt);
        System.out.println();
        for(Integer j:collection){
            System.out.print(j+" ");
        }
    }
//结果:
1 2 3 5 6 7 
1 2 3 5 6 7 9 8 5 6 7 

当直接使用Arrays.asList()的输出,将其作为一个List,其底层表示的是数组,不能改变数组大小。

public static void main(String[] args) {
        List<Integer> intList= Arrays.asList(3,2,4);
        //增加或删除元素,会导致出现异常:UnsupportedOperationException
        //intList.add(6);
        //intList.add(4,6);
        //intList.remove(0);
        for(Integer i:intList){
            System.out.println(i+" ");
        }
    }

Arrays.asList()方法会根据元素的实际类型产生正确的List类型:

public class AsListInference {
    public static void main(String[] args) {
        List<Snow> sonw= Arrays.asList(new Power(),new Crusty(),new Slush());
        //不能编译通过
        //List<Snow> snows_1=Arrays.asList(new Light(),new Heavy());
        //混合情况也不能编译
        //List<Snow> snow_2=Arrays.asList(new Power(),new Light());
        //正确的方法,创建一个空的collection对象,在进行填充
        List<Snow> snows_3=new ArrayList<Snow>();
        Collections.addAll(snows_3,new Light(),new Heavy());
        //也可以使用显式类型参数说明,告诉编译器List的实际类型,
        List<Snow> snows_4=Arrays.<Snow>asList(new Light(),new Heavy());
    }
}

class Snow{}
class Power extends Snow{}
class Light extends Power{}
class Heavy extends Power{}
class Crusty extends Snow{}
class Slush extends Snow{}

打印数组中的元素可以使用Array.toString()方法,但是容器可以直接打印:

public class PrintContain {
    static Collection fill(Collection<String> collection){
        collection.add("rat");
        collection.add("cat");
        collection.add("dog");
        collection.add("dog");
        return collection;
    }

    public static void main(String[] args) {
        //打印数组
        String[] str=new String[]{"rat","cat","dog","dog"};
        System.out.println(Arrays.toString(str));
        //打印容器
        System.out.println(fill(new ArrayList<String>()));
        System.out.println(fill(new LinkedList<String>()));
        System.out.println(fill(new HashSet<String>()));
        System.out.println(fill(new TreeSet<String>()));
        System.out.println(fill(new LinkedHashSet<String>()));
    }
}
//结果
//打印数组
[rat, cat, dog, dog]
//List类型按照插入的顺序保存元素
[rat, cat, dog, dog]
[rat, cat, dog, dog]
//Set类型,每个相同的项保存一次
//HashSet能最快获取元素,存储顺序无意义
[rat, cat, dog]
//TreeSet按照比较结果升序保存对象
[cat, dog, rat]
//LinkedHashSet按照被添加的顺序保存对象
[rat, cat, dog]

List容器
List可以将元素维护在特定的序列中,可以在List的中间插入和移除元素。
两种类型的List:
1、ArrayList:擅长随机访问元素,但在其中插入和移除元素时较慢
2、LinkedList:方便在List中间进行插入和删除操作,在随机访问方面比较慢。

迭代器
迭代器是一个轻量级对象,主要是遍历并选择序列中的对象,而不必关系该序列底层的结构。Java中的Iterator只能单向移动(也就是只能next,向前移动)。

public static void main(String[] args) {
        List<String> strList=new ArrayList<String>();
        Collections.addAll(strList,"dog","cat","mouse","rate");
        //不必关心容器的确切类型
        //方法iterator()返回一个Iterator,将返回序列的第一个元素
        Iterator<String> iterator=strList.iterator();
        //hasNext()检查序列中是否还有元素
        while(iterator.hasNext()){
            //获取序列中的下一个元素
            String str=iterator.next();
            System.out.print(str+" ");
        }
        System.out.println();
        //因为iterator已经到最后没有元素了,需要重新建立对象
        iterator=strList.iterator();
        for(int i=0;i<2;i++){
            //将新近返回的元素删除
            iterator.next();
            iterator.remove();
        }
        System.out.print(strList);

    }
结果:
dog cat mouse rate 
[mouse, rate]

ListIterator
它是Iterator的子类型,只能用于各种List类的访问。并且可以双向移动。

public static void main(String[] args) {
        List<String> petList=new ArrayList<String>();
        Collections.addAll(petList,"dog","cat","pig","rate");
        ListIterator<String> li=petList.listIterator();
        while (li.hasNext()){
            //返回迭代器在列表中指向的当前位置的前一个和后一个元素的索引
           String ne= li.next();
           int next= li.nextIndex();
           int pre= li.previousIndex();
            System.out.print(ne+" "+next+" "+pre+" ");
        }
        System.out.println();
        //也可以反向移动
        while (li.hasPrevious()){
           String previous= li.previous();
            System.out.print(previous+" ");
        }

        System.out.println();
        //可以一开始就指向列表索引为2的元素处的ListIterator
        li=petList.listIterator(2);
        while (li.hasNext()){
            System.out.print(li.next()+" ");
        }
    }
//结果:
dog 1 0 cat 2 1 pig 3 2 rate 4 3 
rate pig cat dog 
pig rate 

LinkedList
在List中插入和移除操作的效率比ArrayList更高效。但在随机访问方面要逊色一些。

public static void main(String[] args) {
        List<String> link=new LinkedList<String>();
        Collections.addAll(link,"dog","rat","mutt","pugl");
        System.out.println("link="+link);
        //返回列表的第一个元素
        //list中没有addFirst()方法
        System.out.println("link.get()="+link.get(0));
        //移除并返回元素
        System.out.println("link.remove()="+link.remove(1));
    }
//结果
link=[dog, rat, mutt, pugl]
link.get()=dog
link.remove()=rat

Stack
栈指后进先出的容器,最后压入栈的元素,最后弹出栈。
LinkedList能够直接实现栈的所有功能的方法,因此可以直接将LinkedList作为栈使用。

public class StackTest<T> {
    //Stack是用LinkedList实现的
    private LinkedList<T> storge=new LinkedList<T>();
    //插入一个元素
    public void push(T t){storge.addFirst(t);}
    //返回栈顶元素,但是并不移除
    public T peek(){return storge.getFirst();}
    //返回并移除栈顶元素
    public T pop(){return storge.removeFirst();}
    //判断栈是否为空
    public boolean empty(){return storge.isEmpty();} 

}

Set
set不保存重复对象。
存储方式的不同:HashSet使用的散列函数,输出的元素没有规律。
TreeSet将元素存储在红-黑树数据结构,对结果进行排序。
LinkedHashSet也使用散列函数,但是使用了链表来维护元素的插入顺序。

HashSet 和TreeSet

public static void main(String[] args) {
        Random random=new Random(100);
        Set<Integer> intset=new HashSet<Integer>();
        Set<Integer> treeSet=new TreeSet<Integer>();
        Collections.addAll(intset,21,32,4,6,1);
        Collections.addAll(treeSet,21,32,4,6,1);
        Iterator<Integer> it=intset.iterator();
        while(it.hasNext()){
            //遍历HashSet,输出的顺序没有规律可循
            System.out.print(it.next()+" ");
        }
        System.out.println();
        Iterator<Integer> itTree=treeSet.iterator();
        while(itTree.hasNext()){
            //遍历TreeSet,对结果进行排序
            System.out.print(itTree.next()+" ");
        }
    }
  //结果
  32 1 4 21 6 
  1 4 6 21 32 

Map

public static void main(String[] args) {
        Map<String,String> petMap=new HashMap<String, String>();
        petMap.put("my Cat","Molly");
        petMap.put("my dog","ginger");
        petMap.put("MY Mamster","Bosco");
        //map中包含某个键或值
        petMap.containsKey("my dog");
        petMap.containsValue("my Cat");
        //遍历map
        //keySet返回键的Set
        for(String my:petMap.keySet()){
            System.out.println("主人:"+my+"宠物:"+petMap.get(my));
        }
        //values返回值的collection
        Iterator<String> valIte=petMap.values().iterator();
        while(valIte.hasNext()){
            System.out.println(valIte.next());
        }
    }

Queue
队列是典型的先进先出的容器。从容器的一端放入事物,从另一端取出,并且事物放入容器的顺序与取出的顺序是相同的。队列可以安全的将对象从一个任务传输给另一个任务。
LinkedList实现了Queue接口,可以把它作为一种实现。

public static void main(String[] args) {
        Queue<Integer> queue=new LinkedList<Integer>();
        Random random=new Random(47);
        //offer方法将一个元素插入到队尾,返回true
        System.out.println(queue.offer(444));
        for(int i=0;i<10;i++){
            queue.offer(random.nextInt(i+10));
        }
        System.out.println(queue);
    }

Collection和Iterator
Collection是描述所有序列容器的共性的根接口,它会被认为是一个附属接口,为了表示其他接口的共性而出现的接口。AbstractCollection提供Collection的默认实现,在穿件AbstractCollection的子类型时,而其中没有不必要的代码的重复。

迭代器和容器都可以用在Map或Collection的子类型来工作。

//使用迭代器
    public static void display(Iterator<String> it){
        while (it.hasNext()){
            System.out.print(it.next()+"  ");
        }
    }
    //使用容器
    public static void display(Collection<String> c){
        for(String str:c){
            System.out.println(str+" ");
        }
    }

    public static void main(String[] args) {
        List<String> strList=new ArrayList<String>();
        Set<String> strSet=new HashSet<String>();
        Collections.addAll(strList,"dog","pig","cat");
        Collections.addAll(strSet,"first","second","third");
        Map<String,String> strMap=new LinkedHashMap<String, String>();
        strMap.put("zhangsan","lisi");
        strMap.put("wangwu","zhaoliu");

        //使用迭代器
        display(strList.iterator());
        display(strSet.iterator());
        display(strMap.keySet().iterator());

        //使用容器
        display(strList);
        display(strSet);
        display(strMap.values());

    }

当要实现一个不是Collection的外部类时,让其实现该接口会非常困难,即使通过继承AbstractCollection而很容易实现,但是还是需要强制实现iterator()和size()方法。此时使用迭代器比较方便。

Foreach与迭代器
foreach语法主要用于数组,但是也可以应用于任何Collection对象。所有的Collection类(不包括各种Map)都是Iterable类型,数组也不是Iterable类型。Iterable接口包含一个能够产生Iterator的iterator()方法。并且Iterable接口被foreach用来在序列中移动。
任何实现了Iterable的类,都可以将它应用于foreach中。

public static void main(String[] args) {
        Map<String,String> strMap=new HashMap<String, String>();
        strMap.put("one","zhangsan");
        strMap.put("two","lisi");
        strMap.put("three","wangwu");
        for(Map.Entry entry:strMap.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
    }
//结果
one:zhangsan
two:lisi
three:wangwu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值