集合框架-----Collection和Map

集合框架—–Collection和Map

记录一下学习的集合框架,梳理思路,也便于以后的查看。如果有错误之处,还望大家不吝指出,多谢哈。

集合框架之Collection

来张Collection体系图:

这里写图片描述

  • Collection概述:

    • Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。

    • 所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。

  • List

    • 集合中存取的元素有序(存和取的顺序一致),有索引,可以存储重复值。
  • Set

    • 集合中存取的元素无序(存和取的顺序不一致),无索引,不可以存储重复的值。

    注意:因为List和Set都是Collection的子接口,如果想使用接口,就必须使用它的实现类。如: List list = new Arraylist();

  • Collection集合遍历

    • 1,将集合转换成数组,(利用toArray()方法 )再使用for循环遍历即可。
    • 2,迭代器遍历(使用集合中iterator()方法获得Iterator对象)

      • 伪代码如下:
        Iterator it = list.iterator();  //获取Iterator 对象
        while(it.hasNext()) {   //判断集合中是否还有元素
            it.next();             //得到元素值
        }
    • 3,增强for循环遍历

      • 伪代码如下
      Collection c = new ArrayList();
      //Object obj = new Student("张三",23);
      c.add(new Student("张三",23));    //Object obj = new Student("张三",23); 这里会自动类型提升为Object
      c.add(new Student("李四",24));
      c.add(new Student("王五",25));
      c.add(new Student("马六",26));
      for (Object value : c) {
      System.out.println(value);
      }
  • List集合特有的遍历

    • 1,根据List集合的特点:有索引,可以通过 list.get(int index);方法遍历
    • 2,List特有的方法:ListIterator。根据listIterator()方法获得ListIterator迭代器对象。
  • 集合遍历注意事项

    • 当使用Iterator迭代器遍历集合需要增添或修改元素时,很可能会发生并发修改异常(ConcurrentModificationException)。
      • 原因:当遍历集合时,增添或修改集合中元素,使用的是集合的方法,而迭代器并不知道,这就导致出现了并发修改异常。
      • 解决办法:
        • 1,使用普通for循环(通过索引删除,一个集合的最大索引为:list.size() - 1; 注意:索引要字减一)list.remove(index–);
        • 2,使用ListIterator迭代器,因为此迭代器中特有添加和删除的方法。
  • List集合中三个子类的特点

    • ArrayList:底层数据结构是数组,查询修改快,增删慢,线程不安全,但效率高。
    • Vector:底层数据结构是数组,查询修改增删都慢,线程安全,但效率低。
    • LinkedList:底层数据结构是链表,查询修改慢,增删快,线程不安全,但效率高。
    • 结论
      • 查询多用ArrayList
      • 增山多用LinkedList
      • 都多用Arraylist
  • 泛型

    • 如:Collection<String> c = new Arraylist<>();定义了一个泛型为String类型的集合。
    • 使用泛型的好处:
      • 提高安全性(将运行期的错误转换到编译期)
      • 省去强转的麻烦
    • 注意:
      • <>中放的必须是引用数据类型。
      • 前后的泛型必须一致,或者后面的泛型可以省略不写(JDK1.7新特性,菱形泛型)
      • 泛型最好不要定义成Object,没有意义。
  • HashSet集合类(Set集合的实现类)
    • 特点:
      • 方法和Collection中方法一样
      • 当向Set集合中存储重复元素时,返回值为false
      • HashSet的继承体系中有重写toString方法
    • HashSet存储自定义对象:
      • 为了保证元素的唯一性,自定义对象的类中必须重写hashCode()和equals()方法。
        • 当哈希值一样时,才会调用equals()方法。
  • LinkedHashSet集合类(HashSet的子类)
    • 特点:
      • 底层是链表实现的,是Set集合中唯一保证怎么存就怎么取。
      • 该类是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样。
  • TreeSet集合类(Set集合的实现类)
    • 特点:
      • 保证元素的唯一性
      • 可以对元素进行排序
    • 排序的方式(自定义对象时)
      • 自然排序:自定义对象的类需要实现Compareable接口,并重写接口中compareTo()方法。
        • 在TreeSet集合类中如何存储元素取决于compareTo()方法的返回值:
          • 返回值为0:集合中只会存储一个元素。
          • 返回值为正数:集合怎么存,就会怎么输出。
          • 返回值为负数:集合会将存储的元素倒序输出。
        • 来个自然排序的代码:
//自定义对象,Person类
public class Person implements Comparable<Person>{
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    //按照年龄排序
    public int compareTo(Person p) {
        //排序:如果是新的(后进来的)减去老的(先进来的),是从小到大排序。
        //       如果是老的减去新的,就是从大到小排序
        //      this代表新的,p代表老的
        int num = this.age - p.age;     //判断年龄是否相同
        //当年龄相同是,比较姓名是否相同。
        int num2 = num == 0 ? this.name.compareTo(p.name) : num;
        return num2;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }   
}


//测试类
import java.util.TreeSet;

public class TreeSetTest {
    /**
     * 演示
     *  按年龄的大小排序(按年龄从小到大排序)
     * TreeSet存储自定义对象并遍历(按年龄从小到大排序)
     */
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<>();

        ts.add(new Person("zhangsan", 23));
        ts.add(new Person("lisi", 16));
        ts.add(new Person("wangwu", 24));
        ts.add(new Person("zhaoliu", 34));
        ts.add(new Person("aaaa", 44));

        System.out.println(ts);
    }
}
//输出结果:
/*  
[Person [name=lisi, age=16], 
Person [name=zhangsan, age=23], 
Person [name=wangwu, age=24], 
Person [name=zhaoliu, age=34], 
Person [name=aaaa, age=44]]
*/
比较排序:Comparator以内部类的形式实现。
代码如下:
//自定义对象Person类

public class Person {
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

//测试类

import java.util.Comparator;
import java.util.TreeSet;
public class Test5_1 {

    /**
     * 演示
     * TreeSet存储自定义对象并遍历(按照姓名的长度排序)
     */
    public static void main(String[] args) {
        //利用比较器排序(匿名内部类)
        TreeSet<Person> ts = new TreeSet<>(new Comparator<Person>() {

            @Override
            public int compare(Person p1, Person p2) {
                int length = p1.getName().length() - p2.getName().length();
                int num2 = length == 0 ? p1.getName().compareTo(p2.getName()) : length;
                return num2 == 0 ? p1.getAge() - p2.getAge() : num2;
            }
        });
        ts.add(new Person("zhangsan", 23));
        ts.add(new Person("lisi", 25));
        ts.add(new Person("wangwu", 26));
        ts.add(new Person("zhaoliu", 28));
        ts.add(new Person("aaaa", 36));

        System.out.println(ts); 
    }
}
//输出结果
/*
[Person2 [name=aaaa, age=36], 
Person2 [name=lisi, age=25], 
Person2 [name=wangwu, age=26], 
Person2 [name=zhaoliu, age=28], 
Person2 [name=zhangsan, age=23]]

*/

集合框架之Map

来张Map体系图:

这里写图片描述
- Map概述:
- 请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

- Map接口和Collection的区别: 
    - 1,Map接口是双列,而Collection接口是单列。
    - 2,Map体系中键是唯一的,Collection的子体系Set是唯一的。
    - 3,Map集合的数据结构的值针对键有效,跟值无关。Collection集合的数据结构是针对元素有效。
- Map存储键值时: 
    - 代码演示,伪代码如下:
Map<String,Integer> map = new HashMap<>();
Integer i1 = map.put("张三",23);      //返回值为null
Integer i2 = map.put("李四",24);      //返回值为null
Integer i2 = map.put("张三",30);      //返回值为23(出现相同键值对时,不会存储,会覆盖原来的键值对。)
System.out.println(map);    
//输出结果
/*
{张三=30, 李四=24}
*/
  • Map集合遍历
    **注意:**Map集合中没有迭代器
    • A :
      • 1,根据键获取值:首先获取所有键的集合(Set<> set keySet = map.keySet();)接下来就可以使用迭代器了,根据键获取值(map.get(key);
      • 2,增强for循环遍历(和第一种方法相似)
        - for(k ,key : map.keySet()) { System.out.println(key + " = " + map.get(key));}
    • B:根据键值对 对象,获取键和值。
      • 利用entrySet()方法,获得键值对 对象,得到一个Set集合。遍历Set集合。
      • 代码如下(来个完整版的):
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapEntry {

    /**
     * map遍历:
     *      根据键值对 对象,获取键和值。
     */
    public static void main(String[] args) {
        Map<String ,Integer> map = new HashMap<String, Integer>();
        map.put("张三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("赵六", 26);
        map.put("马奇", 27);

        //利用entrySet()方法获取键值对 对象 得到一个set集合(以下两种写法,均可)
        //Map.Entry  这是Map接口内又写了Entry接口
        Set<Map.Entry<String,Integer>> set = map.entrySet();
        //Set<Entry<String,Integer>> set = map.entrySet(); 
        //遍历键值对 对象 set集合
        for (Entry<String, Integer> entry : set) {
            String key = entry.getKey();        //通过键值对 对象 的getKey方法获得键
            Integer value = entry.getValue();   //返回与此项对应的值。
            System.out.println(key + "=" + value);
        }
    }
}
  • HashMap集合类
    • 注意:存储自定义对象时,和HashSet一样,需要重写hashCode()和equals()方法。(键 是自定义对象,值 是引用数据类型)
  • LinkedHashMap集合类
    • 和LinkedHashSet原理一样。
  • TreeMap集合类
    • 和TreeMap原理一样。
  • (面试题)HashMap和Hashtable的区别:
    • 共同点: 底层都是哈希算法,都是双列集合
    • 不同点:
      • A:
        • 1,HashMap是线程不安全的,效率高,JDK1.2版本
        • 2,Hastable是线程安全的,效率低,JDK1.0版本
      • B:
        • 1,HashMap可以存储null键和值
        • 2,Hastable不可以存储null键和值

注意:Collections 是集合的工具类,与集合没有关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值