Java集合

集合的概念

概念

对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。

和数组的区别

  1. 数组长度固定,集合长度不固定
  2. 数组可以存储基本类型和引用类型,集合只能存储引用类型

Collection接口

image-20201104091354287

Collection:该体系的跟接口,代表一组对象,称为“集合”。

List接口的特点:有序、有下标、元素可重复

Set接口的特点:无序、无下标、元素不能重复

常用方法

返回值类型 方法 说明
boolean add(Object obj) 添加一一个对象
boolean addAll (Collection c) 将一个集合中的所有对象添加到此集合中
void clear() 清空此集合中的所有对象
boolean contains (Object o) 检查此集合中是否包含o对象
boolean equals (Object o) 比较此集合是否与指定对象相等
boolean isEmpty() 判断此集合是否为空
boolean remove (Object o) 在此集合中移除o对象
int size() 返回此集合中的元素个数
Object[] toArray() 将此集合转换成数组

Collection接口的使用

public class CollectionTest {
    /**
     * Collection接口的使用
     * 1、添加元素
     * 2、删除元素
     * 3、遍历元素
     * 4、判断
     */
    public static void main(String[] args) {
        //创建集合
        Collection collection = new ArrayList();
        //添加元素
        collection.add("老虎");
        collection.add("狮子");
        collection.add("大象");

        //删除元素
//        collection.remove("狮子");
//        collection.clear();

//        System.out.println(collection);

        //遍历元素  两种方式
        //方法1:使用增强for
        for (Object o : collection) {
            System.out.println(o);
        }

        //方法2:使用迭代器(专门用来遍历数组的一种方式)
        //hasNext()  判断有没有下一个元素
        //next()  获取下一个元素
        //remove() 去删除当前元素

        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            iterator.remove();
        }
        System.out.println(collection);
        
        //判断
        System.out.println(collection.contains("狮子"));
        System.out.println(collection.isEmpty());
    }
}

注意:使用迭代器遍历集合时,不能直接操作集合,你如果要对list进行增删操作,都必须经过Iterator,否则Iterator遍历时会乱,所以直接对list进行删除时,Iterator会抛出ConcurrentModificationException异常

List接口与实现类

List接口

常用方法

返回值类型 方法 说明
void add(int index, Object o) 在index位置插入对象o
boolean addAll(int index, Collection c) 将一个集合中的元素添加到此集合中的index位置
Object get(int index) 返回集合中指定位置的元素
List subList (int fromIndex, int toIndex) 返回fromIndex和toIndex之间的集合元素(留头不留尾)

List接口的使用

/**
 * List集合的使用
 * 特点: 1、有序 有下标 2、可以重复
 */
public class ListTest {
    public static void main(String[] args) {
        //创建集合
        List list = new ArrayList<>();
        //添加元素
        list.add("小米");
        list.add("苹果");
        list.add(0, "华为");

        //删除元素
//        list.remove(1);
//        list.remove("小米");
//        list.clear();

        //遍历List集合  四种方式

        //方式1:使用for循环
        System.out.println("------使用for循环遍历------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        //方式2:使用增强for
        System.out.println("------使用增强for遍历------");
        for (Object o : list) {
            System.out.println(o);
        }

        //方式3:使用迭代器
        System.out.println("------使用Iterator遍历------");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //方式4:使用列表迭代器(ListIterator与Iterator的区别:ListIterator可以向前或向后遍历,添加、删除、修改元素)
        ListIterator listIterator = list.listIterator();

        System.out.println("------使用ListIterator向后遍历------");
        while(listIterator.hasNext()){
            System.out.println(listIterator.nextIndex()+":"+listIterator.next());
        }

        System.out.println("------使用ListIterator向前遍历------");
        while(listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }

        //判断
        System.out.println(list.contains("小米"));
        System.out.println(list.isEmpty());

        //获取位置
        System.out.println(list.indexOf("小米"));
    }
}

使用for循环和ListIterator遍历可以获取元素的下标,使用增强for和Iterator则不能。

List实现类

ArrayList

  • 数组结构实现,查询快、增删慢;
  • JDK1.2版本,运行效率快、线程不安全。

Vector

  • 数组结构实现,查询快、增删慢;
  • JDK1.0版本,运行效率慢,线程安全。

LinkedList

  • 链表结构实现,增删快,查询慢。

ArrayList和LinkedList的区别

image-20201104200940276

泛型

Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。

常见的形式有泛型类,泛型接口,泛型方法。

语法:<T,...> T称为类型占位符,表示一种引用类型

好处:提高代码重用性,防止类型转换异常,提高代码安全性

为什么泛型的类型不能是基本数据类型?

泛型的定义:在程序中我们将一个对象放入集合中,但是集合不会记住对象的类型,当我们再次使用对象的时候,对象变为object类型,而程序中还是原来的类型,我们必须要自己转换其类型,为了解决这个问题,则提出泛型。

泛型要求包容的是对象类型,而基本数据类型在Java中不属于对象。但是基本数据类型有其封装类,且为对象类型。

Set接口与实现类

set接口

特点:无序、无下标、不能重复

方法全部是继承自collection接口

set接口的使用

/**
 * 测试set接口的使用
 * 特点:1、无序、无下标 2、不能重复
 */
public class SetTest {
    public static void main(String[] args) {
        //创建集合
        Set<String> set = new HashSet<>();
        //添加数据
        set.add("华为");
        set.add("小米");
        set.add("苹果");
//        set.add("苹果");
        System.out.println("数据个数:"+set.size());
        System.out.println(set);

        //删除数据
//        set.remove("苹果");
//        set.clear();
//        System.out.println(set);

        //遍历
        //1.使用增强for
        for (String s : set) {
            System.out.println(s);
        }

        //2.使用迭代器
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //判断
        set.contains("小米");
        set.isEmpty();
    }
}

set接口实现类

HashSet

  • 基于HashCode计算元素存放位置
  • 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入。
  • 存储结构:哈希表(数组+链表+红黑树)
  • 存储过程:①根据hashcode计算保存位置,如果此位置为空,则直接保存,如果不为空执行第二步。②在执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表

TreeSet

  • 基于排列顺序实现元素不重复。
  • 实现了SortedSet接口,对集合元素自动排序。
  • 元素对象的类型必须实现Comparable接口,指定排序规则。
  • 通过CompareTo方法确定是否为重复元素。
  • 存储结构:红黑树
  • Comparator实现定制比较(比较器)

TreeSet练习

/**
 * 使用TreeSet集合实现字符串按照长度进行排序
 */
public class TreeSetTest {
    public static void main(String[] args) {
        //创建TreeSet集合  并指定比较规则(使用匿名内部类实现 Comparator 接口)
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 = o1.length()-o2.length();//根据长度进行比较
                int n2 = o1.compareTo(o2);//默认比较方式
                return n1==0?n2:n1;//长度一致执行默认比较方式,长度不一致根据长度比较
            }
        });
        //给集合添加元素
        treeSet.add("hello");
        treeSet.add("zt");
        treeSet.add("Integer");
        treeSet.add("boolean");
        treeSet.add("zhangsan");
        treeSet.add("beijing");

        System.out.println(treeSet);
    }
}

Map接口与实现类

Map接口

image-20201105144808032

Map接口的特点:

  • 用于存储任意键值对(Key-Value)
  • 键:无序、无下标、不允许重复(唯一)
  • 值:无序、无下标、允许重复

常用方法:

返回值类型 方法 说明
void put(K key,V value) 将对象存入到集合中,关联键值,key重复则覆盖原值
0bject get (Object key) 根据键获取对应的值
Set keySet() 返回所有key
Collection values() 返回包含所有值的Collection集合
Set<Map.Entry<K,V>> entrySet() 键值匹配的Set集合

map接口的使用

/**
 * Map接口的使用
 * 特点:1、存放键值对 2、键不能重复,值可以重复 3、无序
 */
public class MapTest {
    public static void main(String[] args) {
        //1.创建Map集合
        HashMap<String, String> map = new HashMap<>();
        //2.添加元素
        map.put("China", "中国");
        map.put("American", "美国");
        map.put("England", "英国");
        map.put("Janpane", "日本");

        //3.删除元素
        map.remove("Janpane");
        System.out.println(map);

        //3.遍历map
        //3.1使用keyset()
        System.out.println("------使用keyset()遍历------");
//        Set<String> keySet = map.keySet();
//        System.out.println(keySet);
        for (String key : map.keySet()) {
            System.out.println(key + ":" + map.get(key));
        }

        //3.2使用entrySet()
        System.out.println("------使用entrySet()遍历------");

        Set<Map.Entry<String, String>> entries = map.entrySet();
//        System.out.println(entries);
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }

        //4.判断
        System.out.println(map.containsKey("China"));
        System.out.println(map.containsValue("日本"));
    }
}

Map接口实现类

HashMap

JDK1. 2版本,线程不安全,运行效率快,允许用null作为key或是value。

数据结构:哈希表(数组+链表+红黑树)

红黑树是JDK1.8之后加入的

构造方法

HashMap()

构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。

负载系数(0.75):当容量超过75%开始进行扩容

总结

  1. HashMap刚创建时,table是null, 为了节省空间,当添加第一 个元素时,table容 量调整为16
  2. 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
  3. jdk1.8当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
  4. jdk1.8当链表长度小于6时,调整成链表
  5. jdk1.8以前,链表是头插入,jdk1 .8以后是尾插入

HashTable

JDK1. 0版本,线程安全,运行效率慢;不允许null作为key或是value。

Propertise

Hashtable的子类, 要求key和value都是String。通常用于配置文件的读取。

TreeMap

实现了SortedMap接口(是Map的子接口),可以对key自动排序。

元素对象的类型必须实现Comparable接口,或者创建集合的时候实现Comparable(比较器)接口,自定义比较方法,不然会报类型强制转换异常ClassCastException

Collections工具类

概念

集合工具类,定义了除了存取以外的集合常用方法。

常用方法

方法 说明
public static void reverse(List<?> list) 反转集合中元素的顺序
public static void shuffle(List<?> list) 随机重置集合元素的顺序
public static void sort(List list) 升序排序(元素类型必须实现Comparable接口)
sort(List list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序

Collections工具类的使用

/**
 * Collections工具类的使用
 */
public class CollectionsTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        list.add(1);
        list.add(66);
        list.add(8);
        list.add(20);
        list.add(108);
        list.add(72);
        list.add(80);

        //sort排序
        System.out.println("排序之前"+list);
        Collections.sort(list);
        System.out.println("排序之后"+list);

        //binarySearch二分查找
        int i = Collections.binarySearch(list,5);
        System.out.println(i);

        //copy复制  注意两个集合的大小必须一致才能复制,所以需要先对list2进行赋值
        List<Integer> list2 = new ArrayList<>();
        for (int j = 0; j <list.size() ; j++) {
            list2.add(0);
        }
        Collections.copy(list2,list);
        System.out.println(list2);

        //reverse反转
        Collections.reverse(list);
        System.out.println("反转之后:"+list);

        //shuffle打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:"+list);

        //List转成数组
        Integer[] array = list.toArray(new Integer[0]);
        System.out.println(array.length);
        System.out.println(Arrays.toString(array));

        //数组转成集合  该集合是一个受限集合,不能添加和删除
        String[] names = {"张三","李四","王五"};
        List<String> strings = Arrays.asList(names);
        System.out.println(strings);
        //把基本数据类型数组转换为集合时,需要把基本数据类型转换为引用数据类型
        int[] num ={100,200,300,400};
        List<int[]> ints = Arrays.asList(num);

        Integer[] num1 ={100,200,300,400};
        List<Integer> integers = Arrays.asList(num1);
    }
}

集合总结

集合的概念:

  • 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。

List集合:

  • 有序、有下标、元素可以重复。 (ArrayList、LinkedList、 Vector)

Set集合:

  • 无序、无下标、元素不可重复。 (HashSet、 TreeSet)

Map集合:

  • 存储一对数据,无序、无下标,键不可重复,值可重复。 (HashMap、 HashTable、 TreeMap)

Collect ions:

  • 集合工具类,定义了除了存取以外的集合常用方法。

TreeMap与TreeSet的区别

TreeSet的部分源码

public TreeSet()                                      // ①
    {
        // 以自然排序方式创建一个新的 TreeMap,
        // 根据该 TreeSet 创建一个 TreeSet,
        // 使用该 TreeMap 的 key 来保存 Set 集合的元素
        this(new TreeMap<E,Object>());
    }
    public TreeSet(Comparator<? super E> comparator)     // ②
    {
        // 以定制排序方式创建一个新的 TreeMap,
        // 根据该 TreeSet 创建一个 TreeSet,
        // 使用该 TreeMap 的 key 来保存 Set 集合的元素
        this(new TreeMap<E,Object>(comparator));
    }

从①和②两个构造方法中可以看出,TreeSet 底层实际使用的存储容器就是 TreeMap。

红黑树

红黑树是一种自平衡排序二叉树,树中每个节点的值,都大于或等于在它的左子树中的所有节点的值,并且小于或等于在它的右子树中的所有节点的值,这确保红黑树运行时可以快速地在树中查找和定位的所需节点。

posted @ 2020-11-05 21:35  GodTao  阅读(124)  评论(0)    收藏  举报