JavaSE 集合类型详解

集合类型


一、Java集合类型继承关系

引用博客园博主冰湖一角的图片

引用"冰湖一角"的图片


引用"冰湖一角"的图片


二、类集接口的介绍

  • Collection
    位于类集接口顶层,声明所有类集的核心方法,学习Collection里面的方法很有必要
    image

  • List
    List接口是对Collection接口的扩展,可以存储一系列元素,下标基于0;除了拥有Collection定义的方法以外,List还拥有一些自己的方法
    image

    对add(int index,Object obj)进行测试

    public class Main {
    	public static void main(String[] args) {
    		List list = new ArrayList<>(5);
    		list.add(0,null);
    		list.add(1,'a');
    		list.add(2,'b');
    		list.add(3,'c');
    		list.add(2,'f');
    		System.out.println(list.toString());
    	}
    }//output:[null, a, f, b, c]
    

    对indexOf、lastIndexOf测试

    public class Main {
    	public static void main(String[] args) {
    		List list = new ArrayList<>(5);
    		list.add(0,null);
    		list.add(1,'a');
    		list.add(2,'a');
    		list.add(3,'a');
    		list.add(4,'a');
    		System.out.println(list.indexOf('a'));
    		System.out.println(list.lastIndexOf('a'));
    	}
    }//output:1 4
    

    对remove进行测试

    public class Main {
    	public static void main(String[] args) {
    		List list = new ArrayList<>(5);
    		list.add(0,null);
    		list.add(1,'a');
    		list.add(2,'b');
    		list.add(3,'c');
    		list.add(4,'d');
    		System.out.println(list.lastIndexOf('d'));
    		list.remove(2);
    		System.out.println(list.lastIndexOf('d'));
    	}
    }//output:4 3 证明list里面元素是紧凑的,删除元素后会进行压缩
    

    对listIterator进行测试

    public static void main(String[] args) {
        List list = new ArrayList<>(5);
        list.add(0,null);
        list.add(1,'a');
        list.add(2,'b');
        list.add(3,'c');
        list.add(4,'d');
        ListIterator iterator = list.listIterator();
        while (iterator.hasNext())
            System.out.print(iterator.next()+",");
        System.out.println();
        System.out.println("==============");
        iterator = list.listIterator(2);
        while (iterator.hasNext())
            System.out.print(iterator.next()+",");
    }
    //output
    null,a,b,c,d
    ==============
    b,c,d
    
  • Set集合:set集合不允许添加重复的元素

  • SortedSet接口:会将集合中的元素按升序进行排列,SortedSet不允许添加null元素
    自动排序测试

    public static void main(String[] args) {
        SortedSet set = new TreeSet();
        set.add(100);
        set.add(98);
        set.add(265);
        System.out.println(set);
    }//output:98,100,265
    

    image

    headSet(int x) 返回小于指定值的元素集合

    tailSet(int x) 返回大于等于指定值的元素集合

  • ArrayList 类:实现动态增长容量,随机存储性能较好

    ArrayList有三种构造方法:ArrayList(), ArrayList(Collection c), ArrayList(int initCapacity)

    ArrayList的其他方法:

    • ensureCapacity 可以指定ArrayList的大小,因为每次添加元素动态扩展后,是十分花时间的
  • LinkedList 类:继承了AbstractSequentialList,在头尾添加、删除、修改、查询元素性能较快,会自动地伸长和压缩
    有两种构造函数 LinkedList(Collection c) LinkedList()
    常用的函数:addFirst addLast getFirst getLast removeFirst removeLast

  • HashSet 类扩展AbstractSet接口并实现Set接口,其基于散列码进行存储,速度较快,但元素排序是无序的, 如果你需要有序的Set,请使用TreeSet

//无序的验证
public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"B", "A", "D", "E", "C", "F"});
        HashSet hs = new HashSet(list);
        System.out.println(hs);
    }
} //output:A B C D E F
  • HashSet的四种构造方法:

    • HashSet()
    • HashSet(Collection c)
    • HashSet(int initCapacity)
    • HashSet(int initCapacity, float fillRatio) fillRatio是装载因子,范围在0-1.0之间,默认是0.75。当实际元素个数/容量 > fillRatio, HashSet自动进行扩容
  • TreeSet 类 对象按照升序排列,检索速度快,包含四种构造器

    • TreeSet()
    • TreeSet(Collection c)
    • TreeSet(Comparator comp) 按照指定的办法进行排序
    • TreeSet(SortedSet ss)

三、通过迭代器访问集合里的元素

使用iterator()可以方便地访问每一个元素,iterator()要么实现了Iterator,要么实现了ListIterator
ListIterator比Iterator丰富的地方在于,它允许向前,向后双端遍历,但只适用于实现List接口的类集

Iterator里面的方法
image

ListIterator里面的方法
image

实战演示

import java.util.*;

public class Main {
    public static void main(String[] args) {
        //初始化ArrayList,并添加元素
        List al = new ArrayList(20);
        al = Arrays.asList(new String[]{"C","A","E","B","D","F"});
        
        //创建单向迭代器
        System.out.println("a1 中原始内容是:");
        Iterator itr = al.iterator();
        while (itr.hasNext()){
            Object element = itr.next();
            System.out.print(String.valueOf(element)+" ");
        }
        
        System.out.println();

        //创建双向迭代器,修改元素
        ListIterator litr = al.listIterator();
        while (litr.hasNext()){
            Object element = litr.next();
            litr.set(String.valueOf(element)+"+");
        }
        System.out.println("a1 被修改之后的内容");
        
        //重定向
        itr = al.iterator();
        while (itr.hasNext()){
            Object element = itr.next();
            System.out.print(String.valueOf(element)+" ");
        }
        
        System.out.println();
        
        System.out.println("反向输出");
        while (litr.hasPrevious()){
            Object element = litr.previous();
            System.out.print(String.valueOf(element)+" ");
        }
        System.out.println();
    }
}
//output:
/*
a1 中原始内容是:
C A E B D F 
a1 被修改之后的内容
C+ A+ E+ B+ D+ F+
反向输出
F+ D+ B+ E+ A+ C+
*/

注意:remove会导致iterator删除next指向的元素,再次使用iterator遍历元素会跳过该元素

public static void main(String[] args) {
        //初始化ArrayList,并添加元素
        ArrayList<String> al = new ArrayList<String>(20);
        al.add("C");
        al.add("A");
        al.add("E");

        ListIterator<String> iterator = al.listIterator();
        while (iterator.hasNext()) {
            String letter = iterator.next();
            if (letter.equals("A")) {
                iterator.remove();
                iterator.previous();
            } else
                System.out.print(letter+" ");
        }
        //从集合中删除元素
        System.out.println("\n已经从集合中删除了元素A");
        for (String a : al) System.out.print(a+" ");
    }
//output:
/*
C C E
从集合中删除元素
C E
*/

Map

Map是一种key-value结构,可以根据key获得value值
key不允许重复,值可以重复
测试map功能

public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("A",1);
        map.put("B",2);
        map.put("C",3);
        map.put("D",4);
        //相同的键会重写覆盖
        map.put("A",5);
        
        //获取键的集合
        Set keySet = map.keySet();
        System.out.println(keySet);
		
        //获取值的集合
        Collection values = map.values();
        System.out.println(values);
        
        //获取每一个键值对,进行打印
        for (Map.Entry entry : map.entrySet()) {
            System.out.print("key = "+entry.getKey()+", ");
            System.out.print("value = "+entry.getValue()+"\n");
        }

    }
/*OUTPUT
[A, B, C, D]
[5, 2, 3, 4]
key = A, value = 5
key = B, value = 2
key = C, value = 3
key = D, value = 4
*/

Map接口常用的方法
image
image

Map接口常用的有三个实现类,分别是:AbstractMap,HashMap(散列表结构),TreeMap(树结构)

HashMap不保证加入的顺序,有四种构造器,分别是

  • HashMap()
  • HashMap(Collection c)
  • HashMap(int initCapacity)
  • HashMap(int initCapacity, float fillRatio) fillRatio是装载因子,范围在0-1.0之间,默认是0.75。当实际元素个数/容量 > fillRatio, HashMap自动进行扩容,以保证检索速度

关于WeakHashMap,它是一个弱关键字映射,就是说如果key不再被使用,会被垃圾回收器回收

Map.Entry和SortedMap

Map.Entry是Map的一个内部类,表达一个 key/value映射关系
SortedMap关键字key按升序排序

SortedMap常用的方法
image

TreeMap是实现了SortedMap的完全实现类,其关键字按照升序排序
TreeMap的四种构造方法

image
第二个是传入一个排序策略

public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<String,Integer>();
        map.put("D",4);
        map.put("C",3);
        map.put("B",2);
        map.put("A",1);
        //获取键的集合
        Set keySet = map.keySet();
        //按照升序排列
        System.out.println(keySet);

    }
/*OUTPUT: [A, B, C, D]

Comparator接口

前面说过,TreeMap和TreeSet都可以基于Comparator提供的策略对插入的元素进行排序
comparator接口有两个方法,其中核心的方法是比较两个元素的关系

演示:定义一个基于字符串长度进行排序的策略

public class ComparatorBasedOnStringLength implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
}
public static void main(String[] args) {
        TreeSet<String> set1 = new TreeSet<String>();
        set1.add("AUUUU");
        set1.add("BBFFFFFFFFFF");
        set1.add("CCC");
        System.out.println("基于默认排序策略:字典序");
        System.out.println(set1);

        set1 = new TreeSet<String>(new ComparatorBasedOnStringLength());
        set1.add("AUUUU");
        set1.add("BBFFFFFFFFFF");
        set1.add("CCC");
        System.out.println("基于自定义排序策略:字符串长度由短到长");
        System.out.println(set1);

    }
/*
output:
基于默认排序策略:字典序
[AUUUU, BBFFFFFFFFFF, CCC]
基于自定义排序策略:字符串长度由短到长
[CCC, AUUUU, BBFFFFFFFFFF]
*/

其他集合类介绍

这部分类是以前JDK版本遗留下来的,现在也被归并到类集框架

Enumeration接口

该类的功能与Iterator相似,很少被使用,有两个方法

hasMoreElements 是否有更多的元素,返回是或否
nextElement 返回下一个元素

Vector类

Vector与ArrayList类似,都是动态数组,Vector实现了AbstractList接口和List接口;
区别在于Vector是同步的,而且有以前版本遗留的方法,我们既可以使用List接口的方法,也可以使用以前的方法;
Vector的构造方法

  • public Vector(int initialCapacity, int capacityIncrement)
  • public Vector() 初始容量大小为10
  • public Vector(int initialCapacity) 这里的capacityIncrement = 0,没有指定自增扩容默认扩原来的一倍
  • public Vector(Collection<? extends E> c)

Stack类

Stack是Vector的子类,其元素顺序是后进先出,Stack拥有Vector的所有方法,此外,他还有一些自己的方法。

image

Dictionary类

该类用法与Map类似,也是键值对类型,比较过时

HashTable类

HashTable是同步的,用法与HashMap类似,也是存储键值对类型的数据,我们既可以用Map方法对HashTable进行调用,也可以使用其原本的方法
HashTable有四种构造方法

image

默认装载因子0.75,当把一个Map转为HashTable时,HashTable的容量是原来Map里面元素的两倍,装载因子还是0.75

HashTable有一个方法叫做rehash,它会增大散列表大小,对关键字再散列

Properties类

是HashTable的一个子类,关键字和值都是字符串类型,是线程安全的
Properties类内部还有一个Properties的属性(这看起来很奇怪,但应该是为了适应XML而做的嵌套吧),在对properties进行检索时,如果没有找到,就会去这个对象里面去找,另外Properties支持加载和写入文件

image

一些Properties自带的方法
image

JDK文档说明:Properties虽然可以使用HashTable里面的方法,但还是建议使用SetProperty和GetProperty,否则在调用某些方法上将失败

Properties里面的load和store方法

load允许我们从读入流读取Properties文件转化为Properties对象,store方法允许我们把Properties对象持久化

代码示例

public class TestPropertiesLoadAndStore {
    public static void main(String[] args) {
        Properties settings = new Properties();
        try{
            settings.load(new FileInputStream("d:\\count.txt"));
        }catch (IOException e){
            settings.setProperty("count",new Integer(0).toString());
        }
        int c = Integer.parseInt(settings.getProperty("count"))+1;
        System.out.println("本程序已经被使用"+c+"次");
        settings.setProperty("count",new Integer(c).toString());
        try{
            settings.store(new FileOutputStream("d:\\count.txt"),"PropertiesFile use it");
        }catch (IOException e){
            System.out.println(e.getMessage());
        }
    }
}
posted @ 2022-03-20 13:59  清巡  阅读(110)  评论(0编辑  收藏  举报