Day12——集合

1.集合

在内存层面需要针对于多个数据进行存储。此时可以考虑的容器有:数组、集合类。

  1. 数组存储多个数据方面的特点:
  • 数组一旦初始化,其长度就是确定的。
  • 数组中的多个元素是依次紧密排列的,有序的,可重复的。
  • 数组一旦初始完成,其元素的类型就是确定的。不是此类型的元素无法添加到该数组中。
  • 数组中元素的类型既可以是基本数据类型,也可以是引用数据类型。
  1. 数组存储多个数据方面的弊端:
  • 数组一旦初始化,其长度就不可变。
  • 数组中存储数据特点的单一性。对于无序的、不可重复的场景的多个数据就无能为力。
  • 数组中可用的方法、属性都极少。具体的需求,都需要自己来组织相关的代码逻辑。
  • 针对于数组中元素的删除、插入操作,性能较差。

1.1 Java集合框架体系

  1. java.util.Collection:存储一个一个的数据。
    • 子接口List:存储有序的、可重复的数据(”动态“数组)。ArrayList(主要实现类)、LinkedList、Vector。
    • 子接口Set:存储无序的、不可重复的数据。HashSet、LinkedHashSet、TreeSet。
  2. java.util.Map:存储一对一对的数据。
    • HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties。

1.2 Collection接口及方法

JDK 不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set 和 List)去实现。Collection 接口是 List 和 Set 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 集合。

1.2.1 常用方法

  1. add(Object obj):添加元素对象到当前集合中。
  2. addAll(Collection other):添加 other 集合中的所有元素对象到当前集合中,即 this = this ∪ other。
  3. int size():获取当前集合中实际存储的元素个数。
  4. boolean isEmpty():判断当前集合是否为空集合。
  5. boolean contains(Object obj):判断当前集合中是否存在一个与 obj 对象 equals 返回 true 的元素。
  6. boolean containsAll(Collection coll):判断 coll 集合中的元素是否在当前集合中都存在。即 coll 集合是否是当前集合的“子集”。
  7. boolean equals(Object obj):判断当前集合与 obj 是否相等。
  8. void clear():清空集合元素。
  9. boolean remove(Object obj) :从当前集合中删除第一个找到的与 obj 对象 equals 返回 true 的元素。
  10. boolean removeAll(Collection coll):从当前集合中删除所有与 coll 集合中相同的元素。即 this = this - this ∩ coll。
  11. boolean retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与 coll 集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即 this = this ∩ coll。
  12. Object[] toArray():返回包含当前集合中所有元素的数组。
  13. hashCode():获取集合对象的哈希值。
  14. iterator():返回迭代器对象,用于集合遍历。

1.2.2 集合与数组的相互转换

  1. 集合转数组:toArray()。
  2. 数组转集合:调用Arrays的静态方法asList(Object … objs)。

向Collection中添加元素时,要求元素所属的类一定要重写equals()方法。因为Collection中的相关方法在使用时,要调用元素所在类的equals()方法。

1.3 迭代器接口(Iterator)及方法

  1. 在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK 专门提供了一个接口 java.util.Iterator。Iterator 接口也是 Java 集合中的一员,但它与Collection、Map 接口有所不同。
    • Collection 接口与 Map 接口主要用于存储元素。
    • Iterator,被称为迭代器接口,本身并不提供存储对象的能力,主要用于遍历 Collection 中的元素。
  2. Collection 接口继承了 java.lang.Iterable 接口,该接口有一个 iterator()方法,那么所有实现了 Collection 接口的集合类都有一个 iterator()方法,用以返回一个实现了 Iterator接口的对象。
    • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。
    • 集合对象每次调用 iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

1.3.1 常用方法

  1. public E next():返回迭代的下一个元素。作用1是将指针下移;作用2是将下移以后集合位置上的元素返回。
  2. public boolean hasNext():如果仍有元素可以迭代,则返回 true。
  • 注意:在调用 it.next()方法之前必须要调用 it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用 it.next()会抛出 NoSuchElementException 异常。
    Iterator iterator = coll.iterator();
    while(iterator.hasNext()){
    		System.out.println(iterator.next());
    	}
    

1.3.2 foreach循环

foreach 循环(也称增强 for 循环)是 JDK5.0 中定义的一个高级 for 循环,专门用来遍历数组和集合的。

foreach 循环的语法格式:
for(要遍历的集合或数组元素的类型 临时变量 : 要遍历的集合或数组变量){
 //操作临时变量的输出操作
}
    @Test
    public void test1(){
        Collection coll = new ArrayList();
        coll.add("AA");
        coll.add("BB");
        coll.add(128);
        coll.add(new String("张三"));
        for (Object obj:
             coll) {
            System.out.println(obj);
        }
    }

说明:

  1. 针对于集合来讲,增强for循环的底层仍然使用的是迭代器。
  2. 增强for循环的执行过程中,是将集合或数组中的元素依次赋值给临时变量。注意,循环体中对临时变量的修改,可能不会导致原有集合或数组中元素的修改。

1.4 List接口及方法

List接口用于存储有序的、可以重复的数据。可以使用List替代数组。

1.4.1 常用方法

  1. add(Object obj):添加元素对象到当前集合中。
  2. addAll(Collection other):添加 other 集合中的所有元素对象到当前集合中,即 this = this ∪ other。
  3. int size():获取当前集合中实际存储的元素个数。
  4. boolean isEmpty():判断当前集合是否为空集合。
  5. boolean contains(Object obj):判断当前集合中是否存在一个与 obj 对象 equals 返回 true 的元素。
  6. boolean containsAll(Collection coll):判断 coll 集合中的元素是否在当前集合中都存在。即 coll 集合是否是当前集合的“子集”。
  7. boolean equals(Object obj):判断当前集合与 obj 是否相等。
  8. void clear():清空集合元素。
  9. boolean remove(Object obj) :从当前集合中删除第一个找到的与 obj 对象 equals 返回 true 的元素。
  10. boolean removeAll(Collection coll):从当前集合中删除所有与 coll 集合中相同的元素。即 this = this - this ∩ coll。
  11. boolean retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与 coll 集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即 this = this ∩ coll。
  12. Object[] toArray():返回包含当前集合中所有元素的数组。
  13. hashCode():获取集合对象的哈希值。
  14. iterator():返回迭代器对象,用于集合遍历。
  15. void add(int index, Object ele):在 index 位置插入 ele 元素。
  16. boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来。
  17. Object get(int index):获取指定 index 位置的元素。
  18. List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合。
  19. int indexOf(Object obj):返回 obj 在集合中首次出现的位置。
  20. int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置。
  21. Object remove(int index):移除指定 index 位置的元素,并返回此元素。
  22. Object set(int index, Object ele):设置指定 index 位置的元素为ele。

1.4.2 List 接口的实现类

  1. ArrayList:List的主要实现类,线程不安全但效率高;底层使用Object[]数组存储。
  2. Vector:List的古老实现类,线程安全但效率低;底层使用Object[]数组存储。
  3. LinkedList:底层使用双向链表的方式进行存储。
package p156;

import java.util.ArrayList;
import java.util.Scanner;

public class StudentTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList list = new ArrayList();
        System.out.println("请输入学生信息:");
        while (true){
            System.out.println("1:继续输入,0:结束录入");
            int selection = sc.nextInt();
            if (selection == 0){
                break;
            }
            System.out.print("请输入学生姓名:");
            String name = sc.next();
            System.out.print("请输入学生年龄:");
            int age = sc.nextInt();
            Student s = new Student(name, age);
            list.add(s);
        }
        for (Object arr:list
             ) {
            System.out.println(arr.toString());
        }
        sc.close();
    }
}
package p156;

import java.util.ArrayList;
import java.util.Collection;

public class ListTest {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            list.add((char) (Math.random() * (122 - 97 + 1) + 97) + "");
        }
        int aCount = listTest(list, "a");
        int bCount = listTest(list, "b");
        int cCount = listTest(list, "c");
        int xCount = listTest(list, "x");
        System.out.println(aCount);
        System.out.println(bCount);
        System.out.println(cCount);
        System.out.println(xCount);
    }

    public static int listTest(Collection list, String s){
        int count = 0;
        for (Object obj :
                list) {
            if (s.equals(obj)){
                count++;
            }
        }
        return count;
    }
}

1.5 Set接口及方法

1.5.1 介绍

  1. Set 接口是 Collection 的子接口,Set 接口相较于 Collection 接口没有提供额外的方法。
  2. Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  3. Set 集合支持的遍历方式和 Collection 集合一样:foreach 和 Iterator。
  4. Set 的常用实现类有:HashSet、TreeSet、LinkedHashSet。

1.5.2 HashSet

  1. HashSet 是 Set 接口的主要实现类,大多数时候使用 Set 集合时都使用这个实现类。
  2. HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存储、查找、删除性能。
  3. HashSet 具有以下特点:
    • 不能保证元素的排列顺序。
    • HashSet 不是线程安全的。
    • 集合元素可以是 null。
  4. HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法得到的哈希值相等,并且两个对象的 equals()方法返回值为 true。
  5. 对于存放在 Set 容器中的对象,对应的类一定要重写 hashCode()和 equals(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
  6. HashSet 集合中元素的无序性,不等同于随机性。这里的无序性与元素的添加位置有关。具体来说:我们在添加每一个元素到数组中时,具体的存储位置是由元素的hashCode()调用后返回的 hash 值决定的。导致在数组中每个元素不是依次紧密存放的,表现出一定的无序性。

1.5.3 LinkedHashSet

  1. LinkedHashSet 是 HashSet 的子类,不允许集合元素重复。
  2. LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以添加顺序保存的。
  3. LinkedHashSet 插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。

1.5.4 TreeSet

  1. TreeSet 是 SortedSet 接口的实现类,TreeSet 可以按照添加的元素的指定的属性的大小顺序进行遍历。
  2. TreeSet 底层使用红黑树结构存储数据。
  3. TreeSet 特点:不允许重复、实现排序(自然排序或定制排序)。
  4. 自然排序:默认情况下,TreeSet 采用自然排序(TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列)。
    • 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现Comparable 接口。
    • 实现 Comparable 的类必须实现compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
  5. 定制排序:如果元素所属的类没有实现 Comparable 接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过 Comparator 接口来实现。需要重写compare(T o1,T o2)方法。
    • 利用 int compare(T o1,T o2)方法,比较 o1 和 o2 的大小:如果方法返回正整数,则表示 o1 大于 o2;如果返回 0,表示相等;返回负整数,表示 o1 小于 o2。
    • 要实现定制排序,需要将实现 Comparator 接口的实例作为形参传递给 TreeSet 的构造器。
  6. 因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象。
  7. 对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj) 或 compare(Object o1,Object o2)方法比较返回值。返回值为 0,则认为两个对象相等。
/**
 * 将0-20之间的随机数放入集合中,要求不能出现重复元素
 */
public class Exer02 {
    public static void main(String[] args) {
        HashSet set = new HashSet();
        while (set.size() < 10) {
            int random = (int) (Math.random() * (10 - 1 + 1) + 1);
            set.add(random);
        }
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}
/**
 * 去除列表中重复的元素,仅保留一个即可
 */

public class Exer01 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(34);
        list.add(34);
        list.add(34);
        list.add(24);
        list.add(24);
        list.add(44);
        list.add(44);
        list.add(44);
        List newList = duplicateList(list);
        System.out.println(newList);
    }

    public static List duplicateList(List list){
        HashSet set = new HashSet(list);
        ArrayList list1 = new ArrayList(set);
        return list1;
    }
}

1.6 Map接口及方法

1.6.1 Map及其实现类对比

  1. HashMap:主要实现类,线程不安全但效率高,可以添加null的key和value值,底层使用数组+单向链表+红黑树结构存储(JDK8)。
  2. Hashtable:古老实现类,线程安全但效率低,不可以添加null的key和value值,底层使用数组+单向链表结构存储(JDK8)。
  3. LinkedHashMap:是HashMap的子类,在HashMap使用的数据结构的基础上,增加了一对双向链表,用于记录添加的元素的先后顺序,进而在遍历时可以按照添加的顺序显示。在开发中,对于频繁的遍历操作,建议使用此类。
  4. TreeMap:底层使用红黑树存储,可以按照添加的key-value中的key元素的指定的属性大小顺序进行遍历。需要考虑自然排序定制排序
  5. Properties:是Hashtable的子类,其key和value都是String类型,常用来处理属性文件。

1.6.2 HashMap中元素的特点

  1. HashMap中的所有的key彼此之间是不可重复的、无序的。所有的key构成一个Set集合。key所在的类要重写hashCode()和equals()方法。
  2. HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成了一个Collection集合。value所在的类要重写equals()方法。
  3. HashMap中的一个key-value构成一个entry。HashMap中所有的entry彼此之间是不可重复的、无序的。所有的entry构成了一个Set集合。

1.6.3 Map中的常用方法

  1. 添加、修改操作:
    • Object put(Object key,Object value):将指定 key-value 添加到(或修改)当前map 对象中。
    • void putAll(Map m):将 m 中的所有 key-value 对存放到当前 map 中。
  2. 删除操作:
    • Object remove(Object key):移除指定 key 的 key-value 对,并返回 value。
    • void clear():清空当前 map 中的所有数据。
  3. 元素查询的操作:
    • Object get(Object key):获取指定 key 对应的 value。
    • boolean containsKey(Object key):是否包含指定的 key。
    • boolean containsValue(Object value):是否包含指定的 value。
    • int size():返回 map 中 key-value 对的个数。
    • boolean isEmpty():判断当前 map 是否为空。
    • boolean equals(Object obj):判断当前 map 和参数对象 obj 是否相等。
  4. 元视图操作的方法:
    • Set keySet():返回所有 key 构成的 Set 集合。
    • Collection values():返回所有 value 构成的 Collection 集合。
    • Set entrySet():返回所有 key-value 对构成的 Set 集合。

1.6.4 TreeMap的使用

  1. 底层使用红黑树存储。
  2. 可以按照添加的key-value中的key元素的指定属性大小顺序进行遍历。
  3. 考虑使用自然排序和定制排序。
  4. 要求向TreeMap中添加的的key必须是同一个类型的对象。

1.6.5 Hashtable与Properties的使用

Properties:是Hashtable的子类,其key和value都是String类型,常用来处理属性文件。

package p161;

import java.util.*;

public class SingerTest {
    public static void main(String[] args) {
        HashMap singers = new HashMap();
        String singer1 = "周杰伦";
        ArrayList songs1 = new ArrayList();
        songs1.add("夜曲");
        songs1.add("晴天");
        songs1.add("七里香");
        songs1.add("青花瓷");
        singers.put(singer1,songs1);
        Set entrySet = singers.entrySet();
        Iterator iterator = entrySet.iterator();
        while (iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            System.out.println("歌手:"+entry.getKey());
            System.out.println("歌曲有:"+entry.getValue());
        }
    }
}

1.7 Collections工具类

Collections是一个操作Set、List和Map等集合的工具类。

1.7.1 常用方法

Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法(均为static 方法)。

  1. 排序操作:
    • reverse(List):反转 List 中元素的顺序。
    • shuffle(List):对 List 集合元素进行随机排序。
    • sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序。
    • sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序。
    • swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换。
  2. 查找:
    • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素。
    • Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素。
    • Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素。
    • Object min(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最小元素。
    • int binarySearch(List list,T key):在 List 集合中查找某个元素的下标,但是 List 的元素必须是 T 或 T 的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
    • int binarySearch(List list,T key,Comparator c):在 List 集合中查找某个元素的下标,但是List 的元素必须是 T 或 T 的子类对象,而且集合也事先必须是按照 c 比较器规则进行排序过的,否则结果不确定。
    • int frequency(Collection c,Object o):返回指定集合中指定元素的出现次数。
  3. 复制、替换:
    • void copy(List dest,List src):将 src 中的内容复制到 dest 中。
    • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值。
    • 提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx 的不可修改的视图。
  4. 添加:
    • boolean addAll(Collection c,T… elements):将所有指定元素添加到指定 collection 中。
  5. 同步:
    • Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

你可能感兴趣的:(Java,SE,开发语言,java)