Java基础进阶_day08_(Map集合,可变参数)
博客专区 > Sunmos 的博客 > 博客详情
Java基础进阶_day08_(Map集合,可变参数)
Sunmos 发表于9个月前
Java基础进阶_day08_(Map集合,可变参数)
  • 发表于 9个月前
  • 阅读 3
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

Java基础进阶_day08_(Map集合,可变参数)

1. Map集合

Map集合:将键映射到值的对象.Map集合是双列集合的顶层接口.

# Map集合特点:
* A:一个映射不能包含重复的键(相当于是Collection集合的Set集合);
* B:每个键最多只能映射到一个值;
* C:值可以重复(相当于是Collection集合的List集合).

Map集合与Collection集合的区别:

# Map集合存储的元素是成对出现的,其中键是唯一的,值是可以重复的;
# Collection集合存储的元素是单独出现的,其子接口List集合存储的是元素是可重复的,子接口Set集合存储的元素是唯一的.

集合中的数据结构:

# Map集合的底层数据结构是针对键有效的,对值无效;
# Collection集合的底层数据结构是针对存储的元素有效.

Map集合功能概述:

添加功能:

V put(K key,V value):将指定的键映射到值,返回被替换的值;

获取功能:

Set<Map.Entry<K,V>> entrySet():获取集合键值对的集合;
V get(Object key):获取指定键对应的值,没有则返回null;
Set<K> keySet():返回该集合的键集合;
Collection<V> values():返回该集合的值的集合;

删除功能:

void clear():删除集合中所有的键值对;
V remove(Object key):删除指定键对应的值,并将删除的值返回(key不返回),没有返回null;

判断功能:

boolean containsKey(Object key):判断集合中是否包含指定键;
boolean containsValue(Object value):判断集合中是否包含指定的值;
boolean isEmpty():判断集合是否为空;

长度功能:

int size():返回集合中键值对的对数.

Map集合的遍历方式:

# 方式1:通过keySet()方法获取Map的键的Set集合,通过遍历key的集合(get()方法)获取key对应的value值.
# 方式2:先获取Map集合的键值对对象的集合,通过遍历获取的集合获取每一个键值对对象,获取键值对对象的键和值.

案例:

public class MyMapDemo {
    public static void main(String[] args) {
        //创建集合对象
        Map<Integer, String> m = new HashMap<Integer, String>();
        // V put(K key,V value)
        System.out.println(m.put(1, "郭靖"));
        m.put(2, "黄蓉");
        System.out.println(m);
        // V get(Object key)
        System.out.println(m.get(1));
        System.out.println(m.get(2));
        // Set<K> keySet():
        Set<Integer> keySet = m.keySet();
        for (Integer integer : keySet) {
            System.out.println(integer);
        }
        // Collection<V> values()
        Collection<String> values = m.values();
        for (String string : values) {
            System.out.println(string);
        }
        // void clear()
        // m.clear();
        // System.out.println(m);
        // V remove(Object key)
        System.out.println(m.remove(1));
        System.out.println(m.remove(3));
        // boolean containsKey(Object key)
        System.out.println(m);
        System.out.println(m.containsKey(1));
        // boolean containsValue(Object value)
        System.out.println(m.containsValue("郭靖"));
        // boolean isEmpty()
        System.out.println(m.isEmpty());
        // int size()
        System.out.println(m.size());
        // 遍历集合,方式1
        Map<String, String> map = new HashMap<String, String>();
        map.put("郭靖", "黄蓉");
        map.put("杨康", "穆念慈");
        map.put("周伯通", "瑛姑");
        Set<String> set = map.keySet();
        for (String string : set) {
            System.out.println(string+"..."+map.get(string));
        }
        // 遍历集合,方式1
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey()+"..."+entry.getValue());
        }
    }
}

1.1 HashMap集合

HashMap集合:是基于哈希表的Map集合接口的实现类,其有个子类LinkedHashMap[键值对有序(存取顺序)].

# (键)底层数据结构是哈希表.
# 特点:键值对集合,键唯一,键值对无序(存储顺序),值可以重复.
* 哈希表保证了键的唯一性.
* 任何非null对象都可以用作键或值.

注意事项:

# 由于HashMap集合键的底层数据结构是哈希表,如果键的内容是自定义类,则需要该类重写hashCode和equals方法,否则无法保证键的唯一性.
# HashMap与~~Hashtable~~集合:
 * HashMap集合:线程不安全,效率高,键和值可以为null;
 * Hashtable集合:线程安全,效率低,键和值不允许为null.

案例:

public class MyMap_HashMapDemo {
    public static void main(String[] args) {
        HashMap<Student, String> hm = new HashMap<Student, String>();
        hm.put(new Student("郭靖", 23), "12");
        hm.put(new Student("黄蓉", 23), "13");
        hm.put(new Student("洪七公", 40), "14");
        hm.put(new Student("郭靖", 23), "15");
        Set<Student> keySet = hm.keySet();
        for (Student student : keySet) {
            String s = hm.get(student);
            System.out.println(student.getName()+"..."+student.getAge()+"..."+s);
        }
    }
}
class Student {
    private String name;
    private int age;
    public Student() {}
    public Student(String name, int age) {
        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;
    }
    // 重写hashCode和equals方法
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

1.2 LinkedHashMap集合

LinkedHashMap集合:Map接口的哈希表和链接列表实现,具有可预知的迭代顺序(存储和取出顺序一致),是LinkedHashMap集合是HashMap集合类的子类.

# 底层数据结构是哈希表和链表.
* 特点:键唯一,值可重复,有序(存取顺序一致).
* 哈希表保证了键的唯一性,链表保证了键值对的存取顺序一致.

案例:

public class MyMap_HasMap_LinkedHashMapDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> hm = new LinkedHashMap<String, String>();
        hm.put("123", "java");
        hm.put("1234", "android");
        hm.put("123", "javaEE");
        hm.put("1235", "java");
        Set<String> keySet = hm.keySet();
        for (String string : keySet) {
            System.out.println(string+"..."+hm.get(string));
        }
    }
}

1.3 TreeMap集合

TreeMap集合:是实现了Map集合接口的子类.

# 底层数据结构是红黑树(自平衡的二叉树).
# 特点:键唯一,值可重复,无序(元素存取顺序).
* 键的红黑树数据结构保证了键的唯一性和排序.

构造方法:

public TreeMap():该构造方法的键是自然排序;
public TreeMap(Comparator<? super K> comparator):该构造方法创建的对象的键是按照比较器comparator进行排序.

注意事项:

# 键自然排序:无参构造
 * 当键是自定义对象时,需要该对象所属的类实现Comparable接口,并实现其中的compareTo方法,在该方法中定义排序规则.
# 键比较器排序:有参数构造
 * 当键是自定义对象时,在创建集合对象时,使用实现Comparator接口的匿名内部类,并实现其中的compare方法,在方法中定义排序规则.

案例:

public class MyMap_TreeMapDemo {
    public static void main(String[] args) {
        // 创建集合对象
        TreeMap<Student, String> tm = new TreeMap<Student, String>(new Comparator<Student>() {
            // 重写方法,定义排序规则
            @Override
            public int compare(Student s1, Student s2) {
                // 主要条件,年龄
                int num = s2.getAge() - s1.getAge();
                // 次要条件,姓名
                int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });
        tm.put(new Student("郭靖", 23), "12");
        tm.put(new Student("黄蓉", 23), "13");
        tm.put(new Student("洪七公", 40), "14");
        tm.put(new Student("郭靖", 23), "15");
        Set<Student> keySet = tm.keySet();
        for (Student student : keySet) {
            String s = tm.get(student);
            System.out.println(student.getName()+"..."+student.getAge()+"..."+s);
        }

        // 练习
        // 统计一个字符串中各个字符出现的次数
        test01();
    }

    /* * 统计一个字符串中各个字符出现的次数 */
    public static void test01() {
        // 定义存储字符的集合
        TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
        // 定义键盘录入对象
        Scanner sc = new Scanner(System.in);
        // 定义接收键盘录入的字符串
        System.out.println("请输入一个字符串:");
        String s = sc.nextLine();
        // 将字符串转换为字符数组
        char[] chs = s.toCharArray();

        // 遍历字符数组,统计各个字符出现的次数
        for (int i = 0; i < chs.length; i++) {
            if(tm.containsKey(chs[i])) {
                int num = tm.get(chs[i]);
                num++;
                tm.put(chs[i], num);
            }else {
                tm.put(chs[i], 1);
            }
        }

        // 定义字符串缓冲区对象
        StringBuilder sb = new StringBuilder();
        Set<Character> ketSet = tm.keySet();
        for (Character character : ketSet) {
            sb.append("\""+character+"\"").append("(").append(tm.get(character)).append(")");
        }
        // 输出结果
        System.out.println(sb.toString());

    }
}
// 自定义类
class Person {
    private String name;
    private int age;
    public Person() {}
    public Person(String name, int age) {
        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;
    }
}

2. 可变参数

可变参数:定义方法时不确定参数的个数.

使用格式:

修饰符  返回值类型  方法名 (数据类型...  变量名) {}

注意事项:

# 方法的变量名其实是一个数组;
# 如果一个方法有可变参数并且有多个参数,则可变参数必须是最后一个参数.

Arrays工具类:

public static <T> List<T> asList(T... a):将数组转换为集合.
注意事项:该方法转换成的集合本质还是数组,长度不变,所以不支持改变数组长度的操作(增删),修改可以.

案例:

public class MyArgsDemo {
    public static void main(String[] args) {
        // 调用可变参数方法
        System.out.println(sum(1,2,3));
        System.out.println(sum(1,2));
        System.out.println(sum(1,2,3,4));
        // 多个参数的可变参数,可变参数必须最后一个参数
        System.out.println(sum1(2.4,1,2,3));

        // 将数组转换为集合
        String[] s = {"java","python","android"};
        List<String> asList = Arrays.asList(s);
        // 可变参数
        // List<String> asList = Arrays.asList("java","python","android");
        // List<String> asList = Arrays.asList("java","python");
        for (String string : asList) {
            System.out.println(string);
        }
        // asList.add("java"); // java.lang.UnsupportedOperationException
        // asList.remove(0); // UnsupportedOperationException
        asList.set(0, "java");
    }

    // 定义可变参数
    public static int sum(int... num) {
        int sum = 0;
        // 使用增强for循环遍历数组
        for (int i : num) {
            sum += i;
        }
        return sum;
    }
    // 定义可变参数
    public static int sum1(double num1, int... num2) {
        int sum = 0;
        // 使用增强for循环遍历数组
        for (int i : num2) {
            sum += i;
        }
        System.out.println(num1);
        return sum;
    }
}
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 0
博文 34
码字总数 0
×
Sunmos
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: