Java基础第六天

该文档是:Luo学习Java笔记...

博客连接:https://www.loveuluo.cn

日期:2020-10-31

1. Map集合

image-20201101171325794

1.1 Map接口常用方法

image-20201031104455713

常用方法:

image-20201031105617199

image-20201031105742497

enrtySet方法中Map.Entry是一个静态内部类

1.2 遍历Map集合:

第一种方法:keySet()

    Map<Integer,String> map=new HashMap<>();
    map.put(1,"ligan");
    map.put(2,"czq");
    map.put(3,"wzy");
    map.put(4,"bear");
    //用keySet方法把map集合的key取出来变成set集合
    Set<Integer> keys = map.keySet(); //取出map集合的所有key
    //用迭代器遍历keys 集合
    Iterator<Integer> iterator = keys.iterator();
    while (iterator.hasNext()){
        Integer next = iterator.next();
        System.out.println(map.get(next)); //用get方法放入key获得value
    }
    //用foreach遍历keys 集合
    for (int key : keys){ //key等于是keys集合中的每一个元素
        System.out.println(map.get(key));
    }
}

第二种方法:Set<Map.Entry<K,V>> entrySet()

这种方法是把map集合直接全部转换成Set集合。

Set集合中元素的类型是Map.Entry

image-20201031151253414

public static void main(String[] args) {
    Map<Integer,String> map=new HashMap<>();
    map.put(1,"ligan");
    map.put(2,"czq");
    map.put(3,"wzy");
    map.put(4,"bear");
    Set<Map.Entry<Integer, String>> entries = map.entrySet();
    System.out.println(entries);
    //迭代器遍历方法
    Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();
    while (iterator.hasNext()){
        Map.Entry<Integer, String> next = iterator.next();//遍历Set集合获得每一个Map.Entry<Integer, String> (Integer = String)
        System.out.println(next.getKey()+"="+next.getValue());//用Map.Entry<Integer, String> 的get方法获得key和value
    }
    //foreach方法
    //这种这种方式效率比较高,因为获取key和value都是直接从node对象中取得属性值
    //这种方式比较适合大数据量
    for (Map.Entry<Integer, String> entry : entries) { //用foreach循环拿到每一个Map.Entry<Integer, String>
        System.out.println(entry.getKey()+"="+entry.getValue());//用Map.Entry<Integer, String> 的get方法获得key和value
    }
}

第三种方法:

image-20201031154653252

1.3 哈希表数据结构(*)

image-20201031165313982

image-20201031184008315

重要!:

image-20201031192017369

image-20201031192603210

初始化容量和加载因子:

image-20201101170438163

image-20201031192706837

当往Map集合中存入自己写的类的时候,equals方法和hashCode方法详解:

*提示:hashCode和equals方法需要同时生成

image-20201101160736981

image-20201101161918299

image-20201101162329363

User类:

public class User {
    private String name;
    private int age;
    private String like;

    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setLike(String like) {
        this.like = like;
    }
    @Override
    public boolean equals(Object o) { //重写equals方法,当age和name是一样的时候代表是同一个人
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name);
    }
    @Override
    public int hashCode() { //重写hashCode方法
        return Objects.hash(name, age);
    }
}

测试HashSet集合(HashSet底层就是放入了Hashmap的key中):

public class MapTest {
    public static void main(String[] args) {
        User user1=new User();
        user1.setName("Luo");   user1.setAge(13);  user1.setLike("111");
        User user2 = new User();
        user2.setName("Luo");   user2.setAge(13);  user1.setLike("222");
        Set<User> userMap=new HashSet<>();
        userMap.add(user1);
        userMap.add(user2);
        System.out.println(userMap.size()); //当hashCode值相同的时候会对是这个hashCode值的单向链表的所有节点进行equals,如果 age和name相同则视为同一个 因为不可重复所以会覆盖掉
        System.out.println(user1.hashCode());//没有重写hashCode方法的时候值是460141958 因为HashCode值不同 所以会有两个数组下标,这样的话两个相同的对象就会分开存
        System.out.println(user2.hashCode());//没有重写hashCode方法的时候值是1163157884 重写之后两个对象的hashCode值均为2380968(因为重写的方法中如果age和name相同的话就是一个对象)

    }
}

1.4 Java8对HavaMap集合的改进

在JDK8之后,如果哈希表单向链表中的元素超过8个,单向链表这种数据结构会变成红黑树数据结构。当红黑树上的节点数量小于6时,会重新把红黑树变成单向链表数据结构。这种方式也是为了提高检索效率,二叉树的检索会再次缩小扫描范围。提高效率。

image-20201101171111787

1.5 HashMap key值可以为null

image-20201101184616507

1.6 Hashtable(不建议使用)

image-20201101185401206

1.7 Properties

image-20201102091654431

image-20201102092008592

1.8 TreeMap(实现Comparable接口并实现compareTo方法)

image-20201102093109076

public static void main(String[] args) {
    Set set=new TreeSet();
    set.add("ccbb");
    set.add("bbaa");
    set.add("aabb");
    set.add("aadd");
    for (Object o : set) { //自动升序排序,intger类型同理
        System.out.println(o);//aabb aadd bbaa ccbb 
    }
}

TreeSet无法对自定义类型进排序:

image-20201102101353582

对类型实现Comparable接口并实现compareTo方法就能进行按自己规则定义的排序:

image-20201102111153018

按照年龄升序规则:

public static void main(String[] args) {
    Set<nanTong> set=new TreeSet<>();
    nanTong tong=new nanTong(); tong.age=10; set.add(tong);
    nanTong tong1=new nanTong(); tong1.age=5; set.add(tong1);
    nanTong tong2=new nanTong(); tong2.age=20; set.add(tong2);
        for (nanTong nanTong : set) {
            System.out.println(nanTong);
        }
    }
}
class nanTong implements Comparable<nanTong>{    //这个类必须要实现Comparable接口才能被排序,因为TreeMap底层用了强转为Comparable
    int age;                    //equals方法可以不用重写
    String name;
    //k.compareTo(t.key) (这里的k)其实就是要put进去的对象
    //拿着参数k和集合中的每一个k(t.key)进行比较,返回值可能是>0 <0 =0
    //比较规则最终还是由程序员指定的:例如按照年龄升序。或者按照年龄降序
    @Override//重写compareTo方法 按照自己的规则进行定义
    public int compareTo(nanTong c) {//c1.compareTo(c2);
        //this是c1
        //c是c2
        //c1和c2进行比较的时候,就是this和c比较。
        return this.age-c.age; //这样是正序 反过来就是倒序
    }

按照年龄升序,如果年龄相同的人 按照名字进行升序规则:

public class TreeMapTest01 {
    public static void main(String[] args) {
    Set<nanTong> set=new TreeSet<>();
    nanTong tong=new nanTong(); tong.age=10; tong.name="woyao"; set.add(tong);
    nanTong tong1=new nanTong(); tong1.age=10; tong1.name="wobuyao"; set.add(tong1);
    nanTong tong2=new nanTong(); tong2.age=3; tong2.name="azhe"; set.add(tong2);
        for (nanTong nanTong : set) {
            System.out.println(nanTong);
        }
    }
}
class nanTong implements Comparable<nanTong>{
    int age;
    String name;
    @Override
    public int compareTo(nanTong o) {//重写compareTo方法 按照自己的规则进行定义
    if (this.age == o.age){ //如果年龄相同的人 按照名字进行升序
        return this.name.compareTo(o.name);  //因为String类已经重写了compareTo方法,可以直接调用
    }else {
     return this.age-o.age;
    }
    }
    @Override
    public String toString() { //需要重写toString方法
        return "age="+age+",name="+name;
    }
}

1.9 自平衡二叉树数据结构(*)

每个要放入的数据都是从头开始比,小的放左边大的放右边

image-20201102143858907

底层源码中的代码解析(抽取了一小部分,其实整个是个while循环因为要不停的比较):

cmp = k.compareTo(t.key); //(这里的k)其实就是要put进去的对象
if (cmp < 0) //如果k.compareTo(t.key);小于0就往左边放
    t = t.left; //这里的t.left相当于一个双向链表的t节点,这个传入的数据会被放在t.left之中也就是左边
else if (cmp > 0)
    t = t.right;//如果k.compareTo(t.key);返回结果大于0就往右边放

上诉代码中的cmp其实就是 自定义类中重写的compareTo的返回值。

    nanTong tong1=new nanTong(); tong1.age=5; set.add(tong1);
    nanTong tong2=new nanTong(); tong2.age=20; set.add(tong2);
public int compareTo(nanTong o) {//重写compareTo方法 按照自己的规则进行定义
        /* 这个this.age就相当于上边代码的k 也就是当前对象(要存入的对象)的年龄,而o.age就相当于t.key也就是集合中已经存在的年龄
        而比较规则就是下边的返回值:
        比如说this.age=10 (要存入的)而 o.age=5(集合中存在的年龄),值>0,根据上边的代码>0的放在右边 也就是说如果传入的值和集合中在的值进行比较如果大于那么 要传入的age就会被放到右边  */
        return this.age-o.age; //这样是正序 如果反过来 那么就会变成大的值在左边 小的值在右边
    }

1.10 TreeSet集合元素可排序的第二种方式

Treeset<E>set=new TreeSet<>();括号中需要传入一个比较器,这样的话就不需要实现Comparable方法。

可以使用匿名内部类的方法:

image-20201102165650122

也可以定义一个比较器类:

image-20201102165404441

1.11 传比较器的方法和实现接口的方法哪个好?

img

2.Collections工具类

把线程不安全改成安全的方法:

image-20201102170801996

image-20201102171306639

对List集合进行排序的方法:

第一种是类要实现Comparable接口:

image-20201102171220478

第二种是传入一个比较器:

image-20201102171618398

不能直接对set进行排序,但能把set转化成arraylist集合再进行排序:

image-20201102171500512

最后修改:2020 年 11 月 28 日 09 : 54 AM
如果觉得我的文章对你有用,请随意赞赏