集合Collection和Map

Java集合可分为 Collection 和 Map 两种体系

1、Collection接口:单列数据,定义了存取一组对象的方法的集合

  • List:元素有序、可重复的集合
  • Set:元素无序、不可重复的集合

2、Map接口:双列数据,保存具有映射关系 ”key-value对“ 的集合


一、Collection接口

说明:

  • Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法 既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
  • JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)
    实现。
  • 在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都 当成 Object 类型处理;从 JDK 5.0 增加了泛型以后,Java 集合可以记住容器中对象的数据类型。

1、常用方法

import org.junit.Test;

import java.util.*;

/**
 * 要求:
 * 想Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()
 */
public class test01 {

    @Test
    public void testCollection1(){
        Collection coll = new ArrayList();

        //1.add(Object e):将元素e添加到集合coll中
        coll.add("AA");
        coll.add("BB");
        coll.add(new String("LaLa"));
        coll.add(123);
        coll.add(new Date());

        //2.size():获取添加的元素的个数
        System.out.println(coll.size());//5

        //3.addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
        Collection coll1 = new ArrayList();
        coll1.add(456);
        coll1.add("CC");
        coll1.addAll(coll);

        System.out.println(coll1.size());//7

        //4.clear():清空集合元素
        coll.clear();

        //5.isEmpty():判断当前集合是否为空
        System.out.println(coll.isEmpty());//true


    }

    @Test
    public void testCollection2(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("LaLa"));

        //6.contains(Object obj):判断当前集合中是否包含obj
        //判断时会调用obj对象所在类的equals()
        System.out.println(coll.contains(new String("LaLa")));//true

        //containsAll(Collection coll1):判断形参coll1中的所有元素是否都存在于当前集合中
        Collection coll1 = Arrays.asList(123, 456);
        System.out.println(coll.containsAll(coll1));//true
    }

    @Test
    public void testCollection3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        //7.remove(Object obj):从当前集合中移除obj元素
        coll.remove(123);
        System.out.println(coll);//[456, Tom, false]

        //8.removeAll(Collection coll1):从当前集合中移除coll1中所有的元素(差集)
        Collection coll1 = Arrays.asList(456, 1234);
        coll.removeAll(coll1);
        System.out.println(coll);//[Tom, false]
    }

    @Test
    public void testCollection4(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        //9.retainAll(Collection coll1):获取当前集合和coll1集合的交集,并返回给当前集合
        Collection coll1 = Arrays.asList(123, 456, 789);
        coll.retainAll(coll1);
        System.out.println(coll);//[123, 456]

    }

    @Test
    public void testCollection5(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);
        
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add(456);
        coll1.add(new String("Tom"));
        coll1.add(false);

        //10.equals(Object obj):不仅要相等,还要有序
        System.out.println(coll.equals(coll1));//true
    }

    @Test
    public void testCollection6(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        //11.hashCode():返回当前对象的哈希值
        System.out.println(coll.hashCode());

    }

    @Test
    public void testCollection7(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new String("Tom"));
        coll.add(false);

        //12.集合 ---> 数组:toArray()
        Object[] arr = coll.toArray();
        for(int i = 0; i < arr.length; i++){
            System.out.println(arr[i]);
        }

        //拓展:数组 ---> 集合:调用Arrays类的静态方法asList()
        List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
        System.out.println(list);

        //但是要注意
        List arr2 = Arrays.asList(new int[]{123, 456});
        System.out.println(arr2.size());//1
        List arr3 = Arrays.asList(new Integer[]{123, 456});
        System.out.println(arr3.size());//2
    }
}


二、Collection子接口之一: List接口

说明:

  • List集合类中元素有序、且可重复。
  • JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。

1、常用方法

List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来 操作集合元素的方法。

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * void add(int index, Object ele):在index位置插入ele元素
 * boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
 * Object get(int index):获取指定index位置的元素
 * int indexOf(Object obj):返回obj在集合中首次出现的位置
 * int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
 * Object remove(int index):移除指定index位置的元素,并返回此元素
 * Object set(int index, Object ele):设置指定index位置的元素为ele
 * List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
 */
public class test05 {
    @Test
    public void testList(){
        List list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add(new String("BB"));
        list.add(789);

        //1.void add(int index, Object ele):在index位置插入ele元素
        list.add(1, "BB");


        //2.boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
        List list1 = Arrays.asList(1, 2, 3);
        list.addAll(list1);

        //3.Object get(int index):获取指定index位置的元素
        System.out.println(list.get(1));

        //4.int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1。
        int index = list.indexOf(456);
        System.out.println(index);

        //5.int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
        System.out.println(list.lastIndexOf(456));

        //6.Object remove(int index):移除指定index位置的元素,并返回此元素
        Object obj = list.remove(0);

        //7.Object set(int index, Object ele):设置指定index位置的元素为ele
        list.set(1, "CC");

        //8.List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置左闭右开区间的子集合
        List subList = list.subList(2, 4);
    }
}

2、List实现类之一:ArrayList

说明:

  • ArrayList 是 List 接口的典型实现类、主要实现类
  • ArrayList的JDK1.8之前与之后的实现区别?
    • JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
    • JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元 素时再创建一个始容量为10的数组
  • Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

3、List实现类之二:LinkedList

说明:

  • 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高 。
  • LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last, 用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基 本结构。Node除了保存数据,还定义了两个变量:prev(变量记录前一个元素的位置 )和 next(变量记录下一个元素的位置)。
  • 新增方法:
    • void addFirst(Object obj)
    • void addLast(Object obj)
    • Object getFirst()
    • Object getLast()
    • Object removeFirst()
    • Object removeLast()

4、List 实现类之三:Vector

说明:

  • Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList 相同,区别之处在于Vector是线程安全的。
  • 在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时, 使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
  • 新增方法:
    • void addElement(Object obj)
    • void insertElementAt(Object obj,int index)
    • void setElementAt(Object obj,int index)
    • void removeElement(Object obj)
    • void removeAllElements()

三、 Collection子接口之二: Set接口

说明:

  • Set接口是Collection的子接口,set接口没有提供额外的方法。
  • Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
  • Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法

1、Set实现类之一:HashSet

说明:

  • HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。

  • 不能保证元素的排列顺序 ;HashSet 不是线程安全的 ;集合元素可以是 null。

  • HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

  • 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。

  • 向HashSet中添加元素的过程:

    当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法 来得到该对象的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象 在 HashSet 底层数组中的存储位置。(这个散列函数会与底层数组的长度相计算得到在 数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布, 该散列函数设计的越好)。

    如果两个元素的hashCode()值相等,会再继续调用equals方法,如果equals方法结果 为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了, 那么会通过链表的方式继续链接。

  • 底层也是数组,初始容量为16,当如果使用率超过0.75,(16*0.75=12) 就会扩大容量为原来的2倍。(16扩容为32,依次为64,128....等)

2、Set实现类之二:LinkedHashSet

说明:

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

3、Set实现类之三:TreeSet

说明:

  • TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。

  • TreeSet底层使用红黑树结构存储数据 。

  • 新增方法:

    • Comparator comparator()
    • Object first()
    • Object last()
    • Object lower(Object e)
    • Object higher(Object e)
    • SortedSet subSet(fromElement, toElement)
    • SortedSet headSet(toElement)
    • SortedSet tailSet(fromElement)
  • 只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。

    @Test
    public void test1(){
        TreeSet set = new TreeSet();
    
        //失败:不能添加不同类的对象
        //        set.add(123);
        //        set.add(456);
        //        set.add("AA");
        //        set.add(new User("Tom",12));
    
        //举例一:
        //        set.add(34);
        //        set.add(-34);
        //        set.add(43);
        //        set.add(11);
        //        set.add(8);
    
        //举例二:
        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());
        }
    
    }
    
  • TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。

    //自然排序
    //按照姓名从大到小排列,年龄从小到大排列
        @Override
        public int compareTo(Object o) {
            if(o instanceof User){
                User user = (User)o;
    //            return -this.name.compareTo(user.name);
                int compare = -this.name.compareTo(user.name);
                if(compare != 0){
                    return compare;
                }else{
                    return Integer.compare(this.age,user.age);
                }
            }else{
                throw new RuntimeException("输入的类型不匹配");
            }
    
        }
    
    @Test
    public void test2(){
        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接口

说明:

  • Map与Collection并列存在。用于保存具有映射关系的数据:key-value 。
  • Map 中的 key 和 value 都可以是任何引用类型的数据。
  • Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
  • Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和 Properties。其中,HashMap是 Map 接口使用频率最高的实现类。

1、常用方法:

@Test
public void test3(){
    Map map = new HashMap();
    //1.Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    map.put("AA",123);
    map.put(45,123);
    map.put("BB",56);
    map.put("AA",87);

    Map map1 = new HashMap();
    map1.put("CC",123);
    map1.put("DD",123);

    //2.void putAll(Map m):将m中的所有key-value对存放到当前map中
    map.putAll(map1);

    //3.Object remove(Object key):移除指定key的key-value对,并返回value
    Object value = map.remove("CC");
    System.out.println(value);
    System.out.println(map);

    //4.void clear():清空当前map中的所有数据
    map.clear();//与map = null操作不同
    System.out.println(map.size());
    System.out.println(map);
}
@Test
public void test4(){
    Map map = new HashMap();
    map.put("AA",123);
    map.put(45,123);
    map.put("BB",56);

    //5.Object get(Object key):获取指定key对应的valuey)
    System.out.println(map.get(45));

    //6.boolean containsKey(Object key):是否包含指定的key
    boolean isExist = map.containsKey("BB");
    System.out.println(isExist);

    //7.boolean containsValue(Object value):是否包含指定的value
    isExist = map.containsValue(123);
    System.out.println(isExist);

    map.clear();
    //8.int size():返回map中key-value对的个数
    System.out.println(map.size());

    //9.boolean isEmpty():判断当前map是否为空
    System.out.println(map.isEmpty());

    //10.boolean equals(Object obj):判断当前map和参数对象obj是否相等

}
@Test
public void test5(){
    Map map = new HashMap();
    map.put("AA",123);
    map.put(45,1234);
    map.put("BB",56);

    //11.Set keySet():返回所有key构成的Set集合
    Set set = map.keySet();
    Iterator iterator = set.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }

    //12.Collection values():返回所有value构成的Collection集合
    Collection values = map.values();
    for(Object obj : values){
        System.out.println(obj);
    }

    //13.Set entrySet():返回所有key-value对构成的Set集合
    Set entrySet = map.entrySet();
    Iterator iterator1 = entrySet.iterator();
    while (iterator1.hasNext()){
        Object obj = iterator1.next();
        //entrySet集合中的元素都是entry
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "---->" + entry.getValue());

    }
    System.out.println();
    //方式二:
    Set keySet = map.keySet();
    Iterator iterator2 = keySet.iterator();
    while(iterator2.hasNext()){
        Object key = iterator2.next();
        Object value = map.get(key);
        System.out.println(key + "=====" + value);

    }

}

2、Map实现类之一:HashMap

说明:

  • HashMap是 Map 接口使用频率最高的实现类。
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()。
  • 一个key-value构成一个entry。
  • JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法) 。JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。

3、Map实现类之二:LinkedHashMap

说明:

  • LinkedHashMap 是 HashMap 的子类。
  • 在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序。
  • 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致。

4、Map实现类之三:TreeMap

说明:

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。 TreeMap 可以保证所有的 Key-Value 对处于有序状态。
  • TreeSet底层使用红黑树结构存储数。
  • 自然排序、定制排序

5、Map实现类之四:Hashtable

说明:

  • Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap, Hashtable是线程安全的。
  • Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询 速度快,很多情况下可以互用。
  • 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value。

6、Map实现类之五:Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件。
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型。
  • 存取数据时,建议使用setProperty(String key,String value)方法和 getProperty(String key)方法。
public class PropertiesTest {

    //Properties:常用来处理配置文件。key和value都是String类型
    public static void main(String[] args)  {
        FileInputStream fis = null;
        try {
            Properties pros = new Properties();

            fis = new FileInputStream("jdbc.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();
                }

            }
        }

    }
}
posted @ 2020-03-29 18:02  小燃、  阅读(160)  评论(0编辑  收藏  举报