java集合总结(List Set Map)

数组与集合

集合、数组都是对多个数据进行存储操作的结构。此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储。

  • 数组存储的特点
    一旦初始化以后,其长度就确定了。数组一旦定义好,其元素的类型也就确定了,我们也就只能操作指定类型的数据。
  • 数组存储的弊端
    1、一旦初始化以后,其长度就不可修改。
    2、数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
    3、获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用。
    4、数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。

使用集合存储数据便解决了使用数组存储数据方面的弊端。

Collection接口

  1. 概述
    Collection接口是单列集合,用来存储一个一个的对象。主要有List和Set两个接口。
    1)List接口:存储有序、可重复的数据。(实现类:ArrayList,LinkedList,Vector)。
    2)Set接口:存储无序、不可重复的数据。(实现类:HashSet,LinkedHashSet,TreeSet)。
  2. 常用方法
方法描述
boolean add(Object obj)向集合中添加一个元素
boolean addAll(Collection<> coll)将集合coll中的所有元素添加到原有集合中
int size()返回当前集合中的元素个数
boolean isEmpty()判断当前集合是否为空
boolean contains(Object obj)判断当前集合中是否包含元素obj
boolean containsAll(Collection<> coll)判断当前集合中是否包含集合coll中的所有元素
boolean remove(Object obj)从当前集合中删除元素obj
boolean removeAll(Collection<> coll)从当前集合中删除集合coll中的所有元素
boolean retainAll(Collection<> coll)获取当前集合和集合coll的交集并保留到当前集合中。若当前集合中的内容发生了更改则返回true,否则返回false。
  1. Collection集合与数组之间的转换
    1)集合—>数组:(toArray())
    举例:
    Object[] arr = coll.toArray();
    for(int i = 0;i < arr.length;i++){
    System.out.println(arr[i]);
    }
    2)数组—>集合:调用Arrays类的静态方法asList()
    举例:
List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
System.out.println(list);

List arr1 = Arrays.asList(new int[]{123, 456});
System.out.println(arr1.size());//1

List arr2 = Arrays.asList(new Integer[]{123, 456});
System.out.println(arr2.size());//2

使用Collection集合存储对象须注意:
向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()。

Iterator接口与foreach循环

遍历Collection的两种方式
1、Iterator遍历代码实现

Iterator iterator = coll.iterator();
//hasNext():判断是否还下一个元素
while(iterator.hasNext()){
    //next():指针下移,将下移以后集合位置上的元素返回
    System.out.println(iterator.next());
}

2、foreach遍历代码实现

for(Object obj : coll){
        System.out.println(obj);
    }

Collection子接口:List接口

  1. 存储数据特点
    List存储有序的,可重复的数据。
  2. 常用方法
方法描述
void add(int index, E element)将元素element插入到当前集合中index指向的位置
boolean addAll(int index, Collection<> coll)将集合coll中的所有元素插入到当前集合中index指向的位置。
E remove(int index)将index位置的元素从当前集合移除,返回被删除的元素值,下标不合理时会产生下标越界异常。
E set(int index, E element)使用element元素替换当前集合中index位置的元素,并返回被替换的元素
E get(int index)返回当前集合中下标为index位置的元素
ListsubList(int fromIndex, int toIndex)返回当前集合中从fromIndex到toIndex位置的元素(左闭右开),返回的集合和当前集合共用同一块内存区域。
  1. List接口常用实现类
    (1)ArrayList:作为List接口的主要实现类,线程不安全,效率高,底层使用Object[] elementData存储。
    (2)LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高,底层使用双向链表存储。
    (3)Vector:作为List接口的古老实现类,线程安全的,效率低,底层使用Object[] elementData存储。
  2. ArrayList源码分析
    (1)jdk7的情况
    1)ArrayList list = new ArrayList(),底层创建了长度是10的Object[]数组elementData。
    2)若执行添加操作导致底层elementData数组容量不够,则扩容。默认情况下扩容为原来容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
    3)常用带参构造器:ArrayList list = new ArrayList(int capacity)
    (2)jdk8的情况
    1)ArrayList list = new ArrayList(),底层Object[] elementData初始化为{},并没创建长度为10的数组。
    2)第一次调用add()时,底层才创建了长度10的数组。
  3. LinkedList源码分析
    (1)LinkedList list = new LinkedList(),内部声明了Node类型的first和last属性,默认值为null。
    (2)执行添加操作时将元素封装到Node中,创建了Node对象。
    (3)Node的定义体现了LinkedList的双向链表说法。
  4. Vector源码分析
    通过Vector()构造器创建对象时,底层都创建了长度为10的数组。扩容时,默认扩容为原来的数组长度的2倍。

注意
添加对象时,对象所在的类须重写equals()方法。

Collection子接口:Set接口

  1. 存储数据特点
    存储无序的,不可重复的元素。
    具体以HashSet为例:
    (1)无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
    (2)不可重复性:保证添加的元素按照equals()判断时,不能返回true。即:相同的元素只能添加一个。
  2. 元素添加过程(以HashSet为例)
    (1)向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值。
    (2)此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置)。
    (3)如果此位置上没其他元素,则元素a添加成功。
    (4)如果此位置上有其他元素b(或以链表形式存在的多个元素,则比较元素a与元素b的hash值。
    (5)如果hash值不相同,则元素a添加成功。
    (6)如果hash值相同,进而需要调用元素a所在类的equals()方法:equals()返回true,元素a添加失败, equals()返回false,则元素a添加成功。
  3. 常用方法
    Set接口中没有额外定义新的方法,使用的都是Collection中声明过得方法。
  4. 常用实现类
    (1)HashSet:作为Set接口的主要实现类,线程不安全,可以存储null值。
    (2)LinkedHashSet:是HashSet的子类,可以按照添加顺序遍历其内部数据。其效率高于HashSet。
    (3)TreeSet:可以按照对象的指定属性进行排序。
  5. 存储对象所在类的要求
    Set(主要指:HashSet、LinkedHashSet)中添加的数据时,其所在的类一定要重写hashCode()和equals()方法,且重写的hashCode()和equals()尽可能保持一致性,即:相等的对象必须具有相等的散列码。
  6. TreeSet的使用
    向TreeSet中添加的数据,要求是相同类的对象。
    (1)自然排序:比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()。
    举例:
public void test(){
        TreeSet set = new TreeSet();
        set.add(new User("Tom",12));
        set.add(new User("Jerry",32));
        set.add(new User("Jim",2));
        set.add(new User("Mike",65));
        set.add(new User("Jack",33));
        set.add(new User("Jack",56));


        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }

(2)定制排序:比较两个对象是否相同的标准为:compare()返回0.不再是equals()。
举例(没有使用泛型):

public void test(){
        Comparator com = new Comparator() {
            //照年龄从小到大排列
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User && o2 instanceof User){
                    User u1 = (User)o1;
                    User u2 = (User)o2;
                    return Integer.compare(u1.getAge(),u2.getAge());
                }else{
                    throw new RuntimeException("输入的数据类型不匹配");
                }
            }
        };

        TreeSet set = new TreeSet(com);
        set.add(new User("Tom",12));
        set.add(new User("Jerry",32));
        set.add(new User("Jim",2));
        set.add(new User("Mike",65));
        set.add(new User("Mary",33));
        set.add(new User("Jack",33));
        set.add(new User("Jack",56));


        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

Map接口

  1. 常用实现类
    Map:存储 key—value 对的数据。
    (1)HashMap:是Map的主要实现类,线程不安全,效率高,可以存储null的key和value。
    (2)LinkedHashMap:是HashMap的子类,可以按照添加的顺序实现遍历。原因:在HashMap的底层结构基础上添加了一对指向前一个和后一个元素的指针。
    (3)TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。
    (4)HashTable:作为古老的实现类,线程安全的,效率低,不能存储null的key和value。
    (5)Properties:常用来处理配置文件,key和value都是String类型的。
  2. 存储结构
    (1)Map中的key:无序的,不可重复的,使用Set存储所有的key(存储key时,key所在的类需要重写equals()和hashCode() )。
    (2)Map中的value:无序的,可重复的,使用Collection存储所有的value(存储value时,value所在的类需要重写equals())。
    (3)一个键值对:key-value构成了一个Entry对象。Map中的entry是无序的,不可重复的,使用Set存储所有的entry。
  3. 常用方法
方法描述
E put(K key, E value)用于将指定的key和value组成一对放入当前集合中。增加key和value时则返回null,修改key和value时则返回key之前对应的value。
E remove(Object key)从当前集合删除key关联的键值对。若key不存在则返回null,否则返回key对应的value。
boolean containsKey(Object key)用于判断当前集合中是否存在key
boolean containsValue(Object value)用于判断当前集合中是否存在value
E get(Object key)根据key返回其对应的value
Set<Map.Entry<k, v>>entrySet()将Map转化为Set
Set keySet()返回当前集合中包含key的Set视图
java.util.Map.Entry<k, v>j接口代表键值对,提供的方法有: E getKey():获取当前键值对中key的数值并返回。E getValue():获取当前键值对中value的数值并返回。
  1. 内存结果说明
    (1)jdk7的情况
    1)HashMap map = new HashMap():HashMap在jdk7中的实现原理:在实例化以后,底层创建了长度是16的一维数组Entry[] table。
    2)map.put(key1, value1):
    a、首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
    b、如果此位置上的数据为空,此时的key1-value1添加成功。
    c、如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值。
    d、如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。
    e、如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,如果equals()返回false:此时key1-value1添加成功;如果equals()返回true:使用value1替换value2。
    3)添加元素时,当元素个数超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原的数据复制过来。
    (2)jdk8的情况
    1)new HashMap():底层没创建一个长度为16的数组。
    2)jdk 8底层的数组是:Node[],而非Entry[]。
    3)首次调用put()方法时,底层创建长度为16的数组。
    4)jdk7底层结构为:数组+链表。jdk8中底层结构为:数组+链表+红黑树。
    5)当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。
  2. HashMap底层典型属性的说明:
    (1)DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16。
    (2)DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75。
    (3)threshold:扩容的临界值 = 容量*填充因子:16 * 0.75 => 12。
    (4)TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8。
    (5)MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64
  3. TreeMap的使用
    向TreeMap中添加key-value,要求key必须是由同一个类创建的对象,因为需要按照key进行排序(自然排序 、定制排序)。
  4. 使用Properties读取配置文件
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("user.properties");
        pros.load(fis);//加载流对应的文件

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

Collections工具类的使用

  1. 作用
    操作Collection和Map的工具类。
  2. 常用方法
方法描述
reverse(List)反转List元素的顺序
shuffle(List)对List集合元素进行随机排序
sort(List)根据元素的自然排序对List集合元素进行升序排序
sort(List, Comparator)根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List, int i, int j将list 集合中的 i 处元素和 j 处元素进行交换
Object max(Collection coll)根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection coll,Comparator)根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection coll)根据元素的自然顺序,返回给定集合中的最小元素
Object min(Collection coll,Comparator)根据 Comparator 指定的顺序,返回给定集合中的最小元素
int frequency(Collection coll,Object obj)返回集合中指定元素的出现次数
void copy(List dest,List src)将集合src中的内容复制到集合dest中
boolean replaceAll(List list,Object oldVal,Object newVal)使用新值替换 List 对象的所有旧值
  1. Collection和Collectios的区别
    (1)Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一 个工具类,服务于Java的Collection框架。
    (2).Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值