东软--->Set、Map

 

 

复制代码
package Demo1.JavaSe.NeusoftEdu.zuoye;

import java.time.LocalDate;
import java.util.*;

/**
 * @program: FirstDemo
 * @description: 东软第七天:异常
 * @author: GuoTong
 * @create: 2020-08-19 10:38
 **/
public class day7 {
    /**
     * 继承Exception  就是自定义的编译时异常
     * 继承RuntimeException  就是自定义的运行时异常
     *
     * @param args
     */

    public static void main(String[] args) {
        //  new day7().test();
        /*Exception in thread "main" java.lang.StackOverflowError
    at Demo1.JavaSe.NeusoftEdu.zuoye.day7.test(day7.java:30)
    at Demo1.JavaSe.NeusoftEdu.zuoye.day7.test(day7.java:30)
    at Demo1.JavaSe.NeusoftEdu.zuoye.day7.test(day7.java:30)*/

        try {
            //人造栈溢出:
            new day7().test();
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable e) {
            System.out.println("栈溢出");
        } finally {
            System.out.println("ok");
        }
        System.out.println("NiHao");

    }

    public void test() {
        try {
            int x = 1 / 0;
        } catch (ArithmeticException e) {
            throw new RuntimeException("运行时异常");
        }

        test();

    }

}

class EcmDef {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        boolean flag = true;
        while (flag) {
            try {
                System.out.println("输入除数:");
                int i = Integer.parseInt(scanner.next());
                System.out.println("输入被除数:");
                int j = Integer.parseInt(scanner.next());
                int result = ecm(i, j);
                System.out.println(result);
            } catch (ArithmeticException e) {
                System.out.println("除0异常");
            } catch (NumberFormatException e) {
                System.out.println("异常:您输入的不是一个数?");
            } catch (EcDef e) {
                System.out.println(e.getMessage());
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("缺少命令行参数");
            } finally {
                System.out.println("输入exit退出|任意键继续");
                if (scanner.next().equals("exit"))
                    scanner.close();
                flag = false;
            }
        }

    }

    public static int ecm(int i, int j) throws EcDef {
        if (i < 0 || j < 0) {
            throw new EcDef("自定义异常:分子或分母为负数了!");
        }
        return i / j;
    }
}

class EcDef extends RuntimeException {
    public EcDef(String message) {
        super(message);
    }
}

class ConletionIsMy {

    public static void main(String[] args) {
        Collection collection = new ArrayList();
        collection.add("1");
        collection.add("2");
        collection.add(LocalDate.now());//java 8 时间新特性

        //集合转数组--for循环遍历
        Object[] array = collection.toArray();//集合转化为数组
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        System.out.println("====");
        //迭代器
        //集合的元素进行(CRUD)后,必须要重新获取迭代器,否则会出现异常。
        // IllegalAccessException()
        Iterator iterator = collection.iterator();
        collection.add(new Date());
        iterator = collection.iterator();
        //看看迭代器指针是否还有下一个值
        while (iterator.hasNext()) {
            Object next = iterator.next();//返回当前元素
            System.out.println(next);
        }
        System.out.println("====");

        //foreach  便利
        collection.forEach(System.out::println);
        System.out.println("====");

        //或者增强for循环
        for (Object o : collection) {
            System.out.println(o);
        }

        //清空集合
        collection.clear();
        //集合大小
        int size = collection.size();
        //集合是否为空
        boolean empty = collection.isEmpty();
        //集合是否包含某个元素,contains方法:实际上是通过该类中定义的equals方法判断两个对象是否相等。
        boolean contains = collection.contains("3");
        //删除某个元素
        collection.remove("2");


    }
}

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

        /*int x =10;
        int y = x+(x>>1);//1.5倍扩容
        System.out.println(y);*/
        List list = new ArrayList();//初始化list
        list.add(LocalDate.now());
        list.add("郭童");
        list.add("王尼玛");

        //list可以通过索引取值:list.get(i)
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
            if (i == 2) {
                list.remove(i);
            }
        }
        System.out.println("list集合for循环遍历:删除remove:" + 2 + ":" + list.size());


        for (Object o : list) {
            list.remove(o);//增强for:底层是迭代器:会报错 遍历不能删除操作:快照和·实体不一致
            //但是iterator为什么可以,他删除的时候回吧快照和实体同步。就一致了。
        }
    }
}

class HashSetIsMy {
    private String name;
    private int age;

    public HashSetIsMy(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public HashSetIsMy() {
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("equals....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        HashSetIsMy that = (HashSetIsMy) o;
        return age == that.age &&
                Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
        System.out.println("hashCode!!!");
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "HashSetIsMy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        HashSetIsMy hashSetIsMy = new HashSetIsMy("tom",23);
        HashSetIsMy tom = new HashSetIsMy("tom", 23);
        /*System.out.println(hashSetIsMy.hashCode());
        System.out.println(tom.hashCode());
        System.out.println(hashSetIsMy.hashCode()==tom.hashCode());
        System.out.println("equals:"+tom.equals(hashSetIsMy));*/
        hashSet.add(hashSetIsMy);
        hashSet.add(40);
        hashSet.add(12);
        hashSet.add(tom);
        hashSet.add(-90);
        hashSet.forEach(System.out::println);
    }
}
复制代码

hashCode!!!       第一次调用,是得到对象的hash值,通过该hash值,计算出元素的存储位置
hashCode!!!       第二次调用,是比较添加元素是否和里面的元素的hashcode值是否相等
equals....         如果hashcode值相等,那就比较equals方法,也相等的话就不加入hashset集合。
HashSetIsMy{name='tom', age=23}
40
-90
12

 

 

 

重写hashCode()方法的基本原则

  • 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。

  • 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。

  • 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

重写equals()方法的基本原则

  • 当一个类有自己特有的“逻辑相等”概念,当改写equals()的时候,总是 要改写hashCode(),根据一个类的equals方法(改写后),两个截然不 同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode()方法,它们仅仅是两个对象。

  • 因此,违反了“相等的对象必须具有相等的散列码”。

  • 结论:复写equals方法的时候一般都需要同时复写hashCode方法。通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算

LinkedHashSet实现类

  • LinkedHashSet 是 HashSet 的子类

  • LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。

  • LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。

  • LinkedHashSet 不允许集合元素重复。

TreeSet实现类

  • TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。正因为这个特点,所以查询速度比List快

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

  •  

 

 

TreeSet 两种排序方法

  1. 自然排序

    • TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列

    • 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。

    • 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过compareTo(Object obj) 方法的返回值来比较大小。

    • Comparable 的典型实现:

      • BigDecimal、Integer 以及所有的数值型对应的包装类:按它们对应的数值大小 进行比较

      • Character:按字符的 unicode值来进行比较

      • Boolean:true 对应的包装类实例大于 false 对应的包装类实例

      • String:按字符串中字符的 unicode 值进行比较

  • 向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。

    • 因为只有相同类的两个实例比较大小才有意义,所以向TreeSet中添加的应该是同 一个类的对象。

    • 对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通 过 compareTo(Object obj) 方法比较返回值。

    • 当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保 证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0。否则,让人难以理解。

  1. 定制排序

    • TreeSet的自然排序要求元素所属的类实现Comparable接口,如果元素所属的类没 有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照 其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。

    • 利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

    • 要实现定制排序,需要将实现Comparator接口的实例作为实参传递给TreeSet的构造器。

    • 此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。

    • 使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。

复制代码
class TreeSetTest {
    public static void main(String[] args) {
        TreeSet set = new TreeSet();
       /* set.add(12);
        set.add(3);
        set.add(19);
        set.add(-19);
        set.add(25);
        //tree set 回添加进去后就自动排序的。底层红黑树||一种平衡二叉树*/

        set.add(new TestTreeSetEntity("tom", 12));
        set.add(new TestTreeSetEntity("gt", 22));
        set.add(new TestTreeSetEntity("gte", 12));
        set.add(new TestTreeSetEntity("tom", 11));
        set.add(new TestTreeSetEntity("tosm", 22));
        //如果添加对象进去:
        /*
        Exception in thread "main" java.lang.ClassCastException:
         Demo1.JavaSe.NeusoftEdu.zuoye.HashSetIsMy
         cannot be cast to java.lang.Comparable
         所以需要实现Comparable接口的才能加进去
         */
        set.forEach(System.out::println);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class TestTreeSetEntity implements Comparable {
    private String name;
    private int age;

    //如果是整数,调用者大,如果是0则相等,如果是负数,被调用者大
    /*
    自然排序  implements Comparable
    自定义排序: implements Comparator
TreeSet 会调用集合元素的 compareTo(Object obj)
* 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列
     */
    @Override
    public int compareTo(Object o) {
        int compareAge = age - ((TestTreeSetEntity) o).age;
        if (compareAge != 0)
            return compareAge;
        return name.compareTo(((TestTreeSetEntity) o).name);
    }
}
复制代码

 

Map接口

 Map概述

  • Map与Collection并列存在。用于保存具有映射关系的数据:key-value

  • Map 中的 key 和 value 都可以是任何引用类型的数据

  • Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法

  • 常用String类作为Map的“键”

  • key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value

  • Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类

 

常用方法

  • 添加、删除、修改操作:

    • Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中

    • void putAll(Map m):将m中的所有key-value对存放到当前map中

    • Object remove(Object key):移除指定key的key-value对,并返回value

    • void clear():清空当前map中的所有数据

  • 元素查询的操作:

    • 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是否相等

  • 元视图操作的方法:

    • Set keySet():返回所有key构成的Set集合

    • Collection values():返回所有value构成的Collection集合

    • Set entrySet():返回所有key-value对构成的Set集合

 

HashMap实现类

  • HashMap是 Map 接口使用频率最高的实现类。

  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。

  • 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写: equals()和hashCode()

  • 所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()

  • 一个key-value构成一个entry(node)

  • 所有的entry构成的集合是Set:无序的、不可重复的

  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。

  • HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

 

 

TreeMap实现类

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。

  • TreeMap 可以保证所有的 Key-Value 对处于有序状态。

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

  • TreeMap 的 Key 的排序:

    • 自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有 的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

    • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口

  • TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。

复制代码
class TsetHashMap {
    public static void main(String[] args) {
        HashMap hashMap = new HashMap();
        hashMap.put("1001", "李四");
        hashMap.put("1002", "张三");
        hashMap.put("1003", "王五");

        //遍历map,不可以用迭代器或者for系列。。没有索引,无序
        //方式一:获取所有的key,组成set集合,遍历set集合,通过key获取value
        Set set = hashMap.keySet();//获取所有的key
        for (Object key : set) {
            Object value = hashMap.get(key);
            System.out.println("key:" + key + "\t" + "value" + value);
        }
        //方式二:获取  所有的 键值对(entry)形式:{key=value}    组成的  set集合
        Set entrySet = hashMap.entrySet();
        // entry hashmap$node类型:标识hashmap中的内部类node类型《Map.Entry》
        entrySet.forEach(System.out::println);
        //
        //方式二:第二个方式
        for (Object obj : entrySet) {
            Map.Entry entry = (Map.Entry) obj;
            Object key = entry.getKey();
            Object value = entry.getValue();
            System.out.println("key:" + key + "\t" + "value" + value);
        }
        //获取所有的value的集合
        Collection values = hashMap.values();//无序可重复
        //collection使用迭代器遍历
        Iterator iterator = values.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

    }
}

class TestList {
    public static void main(String[] args) {
        List list = new ArrayList();

        Comparator comparator = new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                return (int) (((StudentB) o1).getScore() - ((StudentB) o2).getScore());
            }
        };
        TreeSet<StudentB> treeSet = new TreeSet<StudentB>(comparator);
        Random random = new Random();
        for (int i = 1; i <= 10; i++) {
            //
            int anInt;
            anInt = random.nextInt(100);
            list.add(anInt);
            treeSet.add(new StudentB("李四" + i, anInt, 100 + i));
        }
        Collections.sort(list);
        list.forEach(System.out::println);
        int i=treeSet.size();
        for (StudentB studentB : treeSet) {
            if (i<=3)
                System.out.println("第"+i+"名"+"分数:"+studentB);
            i--;
        }


    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class StudentB implements Comparable {
    private String name;
    private double score;
    private int id;

   /* public static <T extends Number> T add(T num1,T num2){
        return num1+num2;
    }*/
    @Override
    public int compareTo(Object o) {
        return (int) (score - ((StudentB) o).score);
    }
}
复制代码

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection<E>,List<E>,ArrayList<E> 这个<E>就是类型参数,即泛型。

 

 

自定义泛型结构

泛型的声明

  • interface List<T> 和 class GenTest<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。 常用T表示,是Type的缩写。

泛型的实例化

  • 一定要在类名后面指定类型参数的值(类型)。如:

List strList = new ArrayList();

Iterator iterator = customers.iterator();
  • T只能是类,不能用基本数据类型填充。但可以使用包装类填充

  • 把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想

 

posted on   白嫖老郭  阅读(82)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示