Java的双列集合的基础知识

Java的双列集合的基础知识

双列集合的特点

  1. 键值对存储:双列集合一次存储一对数据,即键和值。这一对数据通常被称为键值对或键值对对象,在Java中,它们被表示为Entry对象。
  2. 键的唯一性:在双列集合中,键(Key)必须是唯一的,不允许重复。这是双列集合的一个重要特性,因为它确保了每个键都能唯一地映射到一个值。如果尝试插入一个已经存在的键,将会替换原有键对应的值。
  3. 值的可重复性:与键不同,值(Value)在双列集合中是可以重复的。这意味着多个键可以映射到相同的值。
  4. 键与值的一一对应关系:在双列集合中,每个键都唯一地对应一个值,形成一对一的映射关系。这种关系使得通过键可以快速找到对应的值。
  5. 支持null值:双列集合中的键和值都可以为空(null)。这意味着你可以在集合中存储空对象作为键或值。
  6. 无序性:双列集合的迭代顺序通常是不确定的,即不保证按照存入顺序或者按照某种排序规则进行遍历。具体的迭代顺序取决于具体的实现类。

Java中的Map接口是双列集合的顶层接口,它定义了一系列用于操作键值对的方法。常见的Map实现类包括HashMap、LinkedHashMap、TreeMap等,它们各自具有不同的特性和适用场景。例如,HashMap基于哈希表实现,提供了快速的插入、删除和查找操作;TreeMap基于红黑树实现,可以对键进行排序;而LinkedHashMap则保持了键值对的插入顺序。

总结来说,双列集合在Java中是一种强大的数据结构,通过键值对的映射关系实现了高效的数据存储和检索功能。

Map

在Java中,Map接口提供了一系列常见的方法来操作键值对。以下是一些常用的Map方法:

  1. put(K key, V value): 将指定的键值对存储到Map中。如果键已经存在,则替换对应的值,并返回之前与该键相关联的值;如果键不存在,则直接添加键值对,并返回null。

  2. get(Object key): 返回与指定键关联的值。如果Map中不包含该键,则返回null。

  3. remove(Object key): 从Map中删除指定键的映射关系,并返回与该键相关联的值。如果键不存在,则返回null。

  4. containsKey(Object key): 检查Map是否包含指定的键。如果存在,则返回true;否则返回false。

  5. containsValue(Object value): 检查Map是否包含指定的值。如果存在,则返回true;否则返回false。

  6. size(): 返回Map中键值对的数量。

  7. isEmpty(): 检查Map是否为空。如果Map不包含任何键值对,则返回true;否则返回false。

  8. keySet(): 返回一个包含Map中所有键的Set集合。

  9. values(): 返回一个包含Map中所有值的Collection集合。

  10. entrySet(): 返回一个包含Map中所有键值对的Set集合。这个集合的每个元素都是Map.Entry类型的对象,表示一个键值对。

  11. putAll(Map<? extends K, ? extends V> m): 将指定Map中的所有映射关系复制到当前Map中。如果当前Map已经包含与指定Map中的键相同的键,则这些键的对应值将被替换。

  12. clear(): 删除Map中的所有键值对。

这些方法提供了对Map的基本操作,包括添加、删除、查找键值对,以及检查Map的状态等。需要注意的是,Map中的键是唯一的,不能有重复的键。如果有重复的键被插入,那么后插入的值会覆盖先插入的值。

Java中的Map接口有多个实现类,如HashMap、TreeMap、LinkedHashMap等,它们各自具有不同的特点和性能。在实际使用中,可以根据具体需求选择合适的实现类。

map的第一种遍历方式:键找值

package com.mohuanan.exercise;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class Demo01 {
    public static void main(String[] args) {
        //map的第一种遍历方式:键找值

        //创建实现Map的对象
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("莫华南", "广西");
        map.put("莫华棋", "广东");
        map.put("莫华程", "北京");
        //获取map集合里面的所有的键
        //存储在单列集合里面
        //keySet()方法的返回值是实现了Set的实现类对象
        Set<String> keys = map.keySet();
        //使用增强for遍历单列集合

        /*for (String key : keys) {
            //根据键找到对应的值
            //key表示里面的每一个元素(键)
            String string = map.get(key);
            System.out.println(key + "=" + string);
        }*/
        //使用迭代器遍历单列集合
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()) {
            String keyString = iterator.next();
            String valueString = map.get(keyString);
            System.out.println(keyString + "=" + valueString);
        }

        System.out.println("-----------");

        //使用lambda表达式进行遍历
        keys.forEach(s ->{
                String valueString = map.get(s);
                System.out.println(s + "=" + valueString);
        });
    }
}
tring);
        }
    }
}

在Java中,不是每一个集合实现类的对象都有iterator()方法。但是,所有的集合框架接口(Collection, Set, List, Queue, Deque等)都继承了Iterable接口,而Iterable接口定义了iterator()方法。因此,任何实现了这些集合框架接口的类都必须提供iterator()方法的实现。

这意味着,如果你有一个实现了Collection, Set, List, Queue, Deque等接口的类的对象,那么你可以调用它的iterator()方法来获取一个迭代器(Iterator),然后使用该迭代器来遍历集合中的元素。

这里有几个例子来说明这一点:

  • ArrayList, LinkedList, HashSet, TreeSet, PriorityQueue等都是实现了集合框架接口的类,因此它们都有iterator()方法。
  • 自定义的类如果实现了集合框架接口(比如通过实现ListSet接口),那么它也必须提供iterator()方法的实现。

然而,有一些类可能不是集合框架的一部分,或者可能只是简单地持有对象的集合,但并不实现集合框架接口。这样的类可能就没有iterator()方法。在这种情况下,如果你想要遍历这些类的对象,你可能需要手动编写遍历逻辑,或者使用其他机制(如循环或递归)来访问对象的元素。

总的来说,如果一个类实现了Java集合框架中的某个接口,那么它就应该有iterator()方法,因为这是接口定义的一部分。但如果一个类不是集合框架的一部分,那么它可能就没有这个方法。

当接口继承另一个接口时,它确实继承了被继承接口的所有抽象方法。在Java中,接口是一种引用类型,它是方法的集合,这些方法默认都是抽象的(即没有方法体)。一个接口可以继承另一个或多个接口,这被称为接口的多重继承。

当一个接口继承另一个接口时,它会自动包含被继承接口中声明的所有方法。这意味着,实现该接口的类必须提供所有这些方法的实现。如果接口A继承了接口B,那么任何实现接口A的类也必须实现接口B中定义的所有方法。

例如:

public interface InterfaceA {
    void methodA();
}

public interface InterfaceB extends InterfaceA {
    void methodB();
}

public class MyClass implements InterfaceB {
    @Override
    public void methodA() {
        // 实现InterfaceA中的methodA方法
    }

    @Override
    public void methodB() {
        // 实现InterfaceB中的methodB方法
    }
}

在上面的例子中,InterfaceB 继承了 InterfaceA,因此 InterfaceB 包含了 methodA()methodB() 两个方法。任何实现 InterfaceB 的类(如 MyClass)都必须提供这两个方法的实现。

这种机制允许接口构建复杂的层次结构,从而可以组合多个接口的功能到一个接口中,进而简化类的实现。

第二种遍历方式 键值对

package com.mohuanan.exercise;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class Demo02 {
    public static void main(String[] args) {
        //创建实现Map的对象
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("莫华南", "广西");
        map.put("莫华棋", "广东");
        map.put("莫华程", "北京");
        //第二种遍历方式 键值对
        //entries存储的是所有的键值对对象
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //1.使用增强for遍历Set集合
        for (Map.Entry<String, String> entry : entries) {
            //Map.Entry Entry是Map里面的内部接口 里面右getKey()方法
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+" "+value);
        }
        System.out.println("-----------------------");
        //2. 使用迭代器遍历Set集合
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();
        while(iterator.hasNext()){
            Map.Entry<String, String> next = iterator.next();
            System.out.println(next);
        }
        System.out.println("--------------------");
        //3. 使用lambda表达式遍历Set集合
        entries.forEach(stringStringEntry-> System.out.println(stringStringEntry));


    }
}

第三种遍历方式 使用lambda表达式

package com.mohuanan.exercise;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class Demo03 {
    public static void main(String[] args) {
        //第三种遍历方式 使用lambda表达式
        //创建一个双列集合
        Map<String,String> map = new HashMap<>();
        //添加元素
        map.put("aaa","111");
        map.put("bbb","222");
        map.put("ccc","333");
        //遍历双列集合
        map.forEach((key,value)-> System.out.println(key+"="+value));

    }
}

HashMap

  • 是map的实现类对象

  • 没有额外需要学习的方法,直接使用Map里面的方法就可以了

  • 特点都是由键决定的:无序,不重复,无索引

  • HashMap和HashSet底层原理是一模一样的,都是哈希表结构

LinkedHashMap
  • 由键决定,有序(就是存和取的顺序是一样的,底层是使用双链表),不重复,无索引

TreeMap

  • 不重复,无索引,可排序
  • 对键进行排序
  • 排序的规则1: 实现Comparable接口,指定比较规则,2: 创建集合时
package com.mohuanan.test;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Test02 {
    public static void main(String[] args) {
        //创建TreeMap对象
        //因为Student是自定义对象
        //所以要重写Student里面的equals和hashCode
        TreeMap<Student, String> tm = new TreeMap<>((o1, o2) -> {
            int i = o1.getAge() - o2.getAge();
            i = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
            return i;

        });
        //创建Student对象
        Student s1 = new Student("eee", 18);
        Student s2 = new Student("add", 12);
        Student s3 = new Student("ad", 12);

        tm.put(s1, "广西");
        tm.put(s2, "北京");
        tm.put(s3, "广东");
        //遍历集合
        Set<Map.Entry<Student, String>> entries = tm.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry);
        }

    }
}

可变参数

  • 方法的形参个数是可以改变的

  • 格式: 数据类型…名字 例子int…a

package com.mohuanan.test;

public class Test04 {
    public static void main(String[] args) {

        int sum = getSum(1,2,3,4,5,6,7,8,9);
        System.out.println(sum);
    }

    //可变参数
    //底层就是一个数组
    //最多只能写一个可变参数
    //并且可变参数只能写在最后
    public static int getSum(int i ,double b ,int...args){
        int sum = 0;

        //System.out.println(args);
        //遍历数组
        for (int arg : args) {
            sum = sum + arg;
        }
        return sum;
    }
}

Collections

  • 不是接口,是一个工具类

Collections是Java的一个工具类,它包含了对集合类(如ListSetMap`等)进行操作的静态方法。这个类不能被实例化,它提供了一组静态方法来操作或返回集合的视图,而不是直接修改集合的内容。

常用的方法

  1. 排序和搜索
  • sort(List<T> list): 对列表进行排序(元素必须实现Comparable接口)。
  • binarySearch(List<? extends Comparable<? super T>> list, T key): 对已排序的列表进行二分搜索。
  1. 修改集合
  • shuffle(List<?> list): 对列表进行随机排序。
  • reverse(List<?> list): 反转列表中的元素顺序。
  • rotate(List<?> list, int distance): 将列表中的元素循环右移指定的距离。
  • addAll(Collection<? super T> c, T... elements): 将所有指定元素添加到指定集合中。
  • fill(List<? super T> list, T obj): 使用指定对象替换列表中的所有元素。
  1. 同步控制
  • synchronizedList(List<T> list): 返回由指定列表支持的同步(线程安全的)列表。
  • synchronizedSet(Set<T> s): 返回由指定集合支持的同步(线程安全的)集合。
  • synchronizedMap(Map<K,V> m): 返回由指定映射支持的同步(线程安全的)映射。
  1. 其他
  • max(Collection<? extends T> coll): 根据元素的自然顺序返回给定集合中的最大元素。
  • min(Collection<? extends T> coll): 根据元素的自然顺序返回给定集合中的最小元素。
  • frequency(Collection<?> c, Object o): 返回指定集合中指定元素的出现次数。
  • disjoint(Collection<?> c1, Collection<?> c2): 如果两个指定集合没有公共元素,则返回true
  • emptyList(), emptySet(), emptyMap(): 返回不可变的空集合视图。

使用的注意事项

  1. 线程安全:默认的集合类(如ArrayListHashSetHashMap)不是线程安全的。如果你在多线程环境中使用它们,并且需要保证操作的原子性,你应该使用Collections的同步方法或者使用并发集合(如CopyOnWriteArrayListConcurrentHashMap等)。
  2. 排序:使用sort()方法对列表进行排序时,列表中的元素必须实现Comparable接口,并且compareTo()方法必须被正确地实现。否则,将会抛出ClassCastException
  3. 二分搜索:使用binarySearch()方法进行二分搜索时,列表必须已经是有序的。如果列表未排序,则结果将是未定义的。
  4. 空指针异常:像sort()binarySearch()等方法可能会抛出NullPointerException,如果传入的集合或列表是null的话。在使用这些方法之前,确保传入的集合或列表不是null
  5. 性能:虽然Collections中的方法提供了很多便利,但它们可能会带来一些性能开销。在使用之前,请考虑是否有更高效的替代方案。
  • 55
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值