thrift rpc 案例

Android 大厂高频面试题及答案,知识脉络整理

  返回  

2021/07/20笔记

2021/7/20 21:23:44 浏览:

我们于2021/07/20 的学习目标是:容器,核心任务为:

1、学习技术:

1)、Set

2)、HashSet

3)、TreeSet

4)、Map <K,V>

5)、HashMap

6)、TreeMap

7)、Properties

8)、Collections类提供的工具

9)、总结

2、文档总结:

1)、Set

特点:无序的,不可重复

新增功能:static <E> Set<E> of(E... elements) 返回包含任意数量元素的不可修改集。

其他方法从Collection继承

遍历方式:foreach iterator

注意:存放数据的顺序与内部真实存储的顺序可能不一致

import java.util.HashSet;

import java.util.Iterator;

import java.util.Set;

public class Class001_Set {

    public static void main(String[] args) {

        Set<String> set = new HashSet<>();

        //去重  无序

        set.add("bcd");

        set.add("abc");

        set.add("abc");//不会重复出现相同的内容

        set.add("bc");

        set.add("ab");



        System.out.println(set);



        //遍历方式

        //foreach

        for(String str:set){

            System.out.println(str);

        }



        //iterator

        Iterator<String> it =  set.iterator();

        while(it.hasNext()){

            System.out.println(it.next());

        }



        //新增

        Set<Integer> set2 = Set.of(3,1,2,5,4);

        System.out.println(set2);

        //对于指定了数据的set不可变

        //set2.remove(3);





        System.out.println(set2);

    }

}

2)、HashSet

HashSet是由HashMap维护的,两者共同。

特点:无序的,不可重复;查询,增删效率较高

底层结构:哈希表(数组+链表+红黑树)

应用场景:存储数据由单个值决定的情况下,想要去重的情况下,适合使用HashSet

哈希表中hashcode与equals之间的关系

(前提是重写hashcode与equals都是根据成员变量计算)

equals相等hashcode一定相等

hashcode相等,equals不一定相等

哈希表存储自定义引用数据类型数据的去重:

需要在数据的类型中重写hashcode与equals方法,实现根据内容(成员变量的值)进行比较和计算

public class Class002_HashSet {

    public static void main(String[] args) {

        HashSet<Person> set = new HashSet<>();



        set.add(new Person("阿杰",18));

        set.add(new Person("绲神",19));

        set.add(new Person("奈克斯",18));



        System.out.println(set);



        System.out.println(new Person("奈克斯",18).hashCode());

        System.out.println(new Person("奈克斯",18).hashCode());



    }

}



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;

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", age=" + age +

                '}';

    }



    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        return age == person.age &&

                Objects.equals(name, person.name);

    }



    @Override

    public int hashCode() {

        return Objects.hash(name, age);

    }

}

3)、TreeSet

TreeSet是由TreeMap维护的,两者有共同之处

特点:无序,去重,默认升序排序

底层结构:红黑树(平衡二叉树)

新增方法:数据的大小比较相关的方法,因为红黑树结构中数据已经比较过大小,默认升序

import java.util.TreeSet;

public class Class003_TreeSet {

    public static void main(String[] args) {

        TreeSet<Double> tree = new TreeSet<>();



        tree.add(3.3);

        tree.add(1.1);

        tree.add(2.2);

        tree.add(4.4);

        tree.add(5.5);

        tree.add(5.5);



        System.out.println(tree);



        //测试新增 方法

        System.out.println(tree.first());

        System.out.println(tree.last());

        System.out.println(tree.ceiling(2.1));

        System.out.println(tree.floor(3.3));



        TreeSet<String> tree2 = new TreeSet<>();



        tree2.add("abc");

        tree2.add("bc");

        tree2.add("ab");

        tree2.add("a");

        tree2.add("b");

        tree2.add("ab");



        System.out.println(tree2);

    }

}

思考:使用TreeSet存储自定义的引用数据类型,如何是否去重(根据内容去重),实现默认升序排序?

问题:在存储自定义引用数据类型数据的时候,对象数据不确定比较规则,在TreeSet无法实现比较,无法排序

需要: 指定学生数据的比较规则

通过内部比较规则|内部比较器|自然排序,实现一个java.lang.Comparable接口,重写compareTo方法,在compareTo方法内部指定比较规则。由于定义在类的内部,是一种默认的比较规则。

实现内部比较器:定义一个TreeSet集合存储学生信息,要求根据学生姓名进行排序,实现根据姓名降序排序

import java.util.TreeSet;

public class Class004_TreeSet {

    public static void main(String[] args) {

        TreeSet<Student> tree = new TreeSet<>();



        tree.add(new Student(103,"zhangsan",19));

        tree.add(new Student(102,"lisi",17));

        tree.add(new Student(101,"zhangsan",18));

        tree.add(new Student(101,"wangwu",16));



        System.out.println(new Student(102,"lisi",17).compareTo(new Student(103,"zhangsan",19)));



        System.out.println(tree);





    }

}

4)、Map <K,V>

特点:

存储键值对数据

元素的集合,键值对的集合

K-V 键值对

key,value可以为任意引用数据类型的数据

key--> 唯一的,无序的 --> Set集合

value --> 无序的,可重复的  -->Collection

K与V的关系:

键值对为一个映射关系

key--> 映射-->value

一个key只能对应一个value

一个key可以实现对应一个集合作为value,集合中可以存放多个值

import java.util.HashMap;

import java.util.Map;

public class Class001_Map {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<>();



        //常用方法

        //V put(K key, V value)  返回被覆盖的value,如果没有覆盖返回null

        System.out.println(map.put(103,"胡歌"));

        System.out.println(map.put(104,"胡歌"));

        System.out.println(map.put(102,"彭于晏"));

        System.out.println(map);

        System.out.println(map.put(104,"胡一菲"));

        System.out.println(map);



        /*

        boolean containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。

        boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true 。

         */

        System.out.println(map.containsKey(104));

        System.out.println(map.containsValue("胡歌"));



        //V get(Object key) 返回指定键映射到的值,如果此映射不包含键的映射,则返回 null 。

        System.out.println(map.get(102));



        //static <K,​V> Map<K,​V> of​(K k1, V v1) 返回包含单个映射的不可修改的映射。

        Map<String,Integer> map2 = Map.of("zhangsan",18,"lisi",19);

        System.out.println(map2);



        //V remove(Object key) 如果存在,则从该映射中移除键的映射(可选操作)。

        System.out.println(map.remove(101));

        System.out.println(map);



        //default V replace(K key, V value) 仅当指定键当前映射到某个值时,才替换该条目的条目。

        map.replace(103,"哥哥");

        System.out.println(map);

    }

}

Map集合的遍历方式:

  1. keySet() 获取集合中所有的key,然后遍历key,根据key获取value
  2. values() 获取集合中所有的value
  3. entrySet() 返回多个Map.Entry类型的键值对对象,一个set集合
import java.util.*;

public class Class002_Map {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<>();



        map.put(103,"胡歌");

        map.put(104,"胡歌");

        map.put(102,"彭于晏");

        map.put(105,"胡一菲");



        //1.keySet

        Set<Integer> keys =  map.keySet();

        for(Integer i : keys){

            System.out.println(i+"-->"+map.get(i));

        }



        //2.values()

        Collection<String> values =  map.values();

        Iterator<String> it = values.iterator();

        while(it.hasNext()){

            System.out.println(it.next());

        }



        //3.entrySet()

        Set<Map.Entry<Integer,String>> set = map.entrySet();

        for(Map.Entry entry:set){

            System.out.println(entry.getKey()+"-->"+entry.getValue());

        }

    }

}

5)、HashMap

底层:哈希表(数组+链表+红黑树)

特点:查询,增删效率高

新增方法:无新增方法

遍历方式: 与map相同

并允许null值和null键

DEFAULT_LOAD_FACTOR : 默认的加载因子     0.75

DEFAULT_INITIAL_CAPACITY : 默认初始容量  1<<4 = 16

threshold 扩容临界值 | 阀值  CAPACITY*LOAD_FACTOR

扩容:newCap = oldCap << 1 每次扩容原数组容量的2倍

去重: key中存储数据的类型要求重写hashcode与equals方法

例:定义一个HashMap结构,用来存储指定类型的数据,要求存储key为Teacher,value为Teacher所教授的学科

import java.util.HashMap;

import java.util.Objects;



public class Class005_HashMap {

    public static void main(String[] args) {

        HashMap<Teacher,String> map = new HashMap<>();



        map.put(new Teacher("A","Math"),"Math");

        map.put(new Teacher("B","English"),"English");

        map.put(new Teacher("C","JavaSE"),"JavaSE");

        map.put(new Teacher("D","SOC"),"SOC");



        System.out.println(map);





    }

}



class Teacher{

    private String name;

    private String subject;



    public Teacher(String name, String subject) {

        this.name = name;

        this.subject = subject;

    }



    public String getName() {

        return name;

    }



    public Teacher setName(String name) {

        this.name = name;

        return this;

    }



    public String getSubject() {

        return subject;

    }



    public Teacher setSubject(String subject) {

        this.subject = subject;

        return this;

    }



    @Override

    public String toString() {

        return "Teacher{" +

                "name='" + name + '\'' +

                ", subject='" + subject + '\'' +

                '}';

    }



    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Teacher teacher = (Teacher) o;

        return Objects.equals(name, teacher.name) &&

                Objects.equals(subject, teacher.subject);

    }



    @Override

    public int hashCode() {

        return Objects.hash(name, subject);

    }

}

6)、TreeMap

特点:根据key去重和做升序排序

底层结构:红黑树

新增功能:比较相关的一些方法

要求: key指定比较规则|方式|(内部|外部)比较器|排序

例:定义TreeMap存储键值对数据,key为Teacher

import java.util.Objects;

import java.util.TreeMap;

public class Class006_TreeMap {

    public static void main(String[] args) {

        TreeMap<Teacher1,String> tree = new TreeMap<>((t1,t2)->t1.getSubject().compareTo(t2.getSubject()));



        tree.put(new Teacher1("A","Math"),"Math");

        tree.put(new Teacher1("B","English"),"English");



        System.out.println(tree);

        System.out.println(tree.firstEntry());

        System.out.println(tree.firstKey());

        System.out.println(tree.pollFirstEntry());

    }

}



class Teacher1{

    private String name;

    private String subject;



    public Teacher1(String name, String subject) {

        this.name = name;

        this.subject = subject;

    }



    public Teacher1() {

    }



    public String getName() {

        return name;

    }



    public Teacher1 setName(String name) {

        this.name = name;

        return this;

    }



    public String getSubject() {

        return subject;

    }



    public Teacher1 setSubject(String subject) {

        this.subject = subject;

        return this;

    }



    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Teacher1 teacher1 = (Teacher1) o;

        return Objects.equals(name, teacher1.name) &&

                Objects.equals(subject, teacher1.subject);

    }



    @Override

    public int hashCode() {

        return Objects.hash(name, subject);

    }



    @Override

    public String toString() {

        return "Teacher1{" +

                "name='" + name + '\'' +

                ", subject='" + subject + '\'' +

                '}';

    }

}

7)、Properties

特点:存储的键值对都是字符串,Properties可以保存到流中或从流中加载。

软解码:经常改动的内容不要定义在源代码中,定义在一个外部的文件中(配置文件),从程序中每次动态从文件中进行读取内容,使用读入的最新内容

import java.io.IOException;

import java.util.Properties;

public class Class005_Properties {

    public static void main(String[] args) throws IOException {

        Properties pro = new Properties();

        //设置键值对为字符串数据

       /* pro.setProperty("name","张三");

        pro.setProperty("pwd","123");*/



        //获取键值对为字符串的数据

        System.out.println(pro.getProperty("name"));



        System.out.println(pro);



        //void load(InputStream inStream) 从输入字节流中读取属性列表(键和元素对)。

        pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));



        //从配置文件中读取数据

        System.out.println(pro.getProperty("name"));

        System.out.println(pro.getProperty("pwd"));

    }

}

8)、Collections类提供的工具

类 java.util.Collections 提供了对Set、List、Map操作的工具方法。


import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class Class001_Collections {

    public static void main(String[] args) {

        /*

            void sort(List)  //对List容器内的元素排序,排序的规则是按照升序进行排序。

            void shuffle(List) //对List容器内的元素进行随机排列

            void reverse(List) //对List容器内的元素进行逆续排列

            void fill(List, Object)  //用一个特定的对象重写整个List容器

            int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象

         */

        List<Integer> list = new ArrayList<>();



        list.add(3);

        list.add(1);

        list.add(2);

        list.add(5);

        list.add(4);



        System.out.println(list);



        //sort 升序排序徐

        Collections.sort(list);

        System.out.println(list);



        //sort(List<T> list, Comparator<? super T> c)



        //shuffle 随机排序

        //Collections.shuffle(list);

        System.out.println(list);



        //void reverse(List)翻转

        //Collections.reverse(list);

        System.out.println(list);



        //binarySearch  如果找到返回索引,找不到返回-插入点-1

        System.out.println(Collections.binarySearch(list,12));

    }

}

9)、总结

如何处理HashMap的线程不安全问题:

1.可以Hashtable

1).线程安全问题

2).HashMap允许key与value为null,Hashtable不允许

3).细节问题,底层源码

2.static <K,V>Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全)映射。

3.juc 高级并发编程包,ConcurrentHashMap<K,V>-->推荐

SE阶段重点知识:面向对象与集合

集合与数组之间的区别:

数组

集合

数据类型

基本数据类型和引用数据类型

引用数据类型

长度

定长

动态调整

存储类型

要求同一个数组内存储的数据类型一致

存储任意引用数据类型

顺序

有序

Collection与Collections之间的区别:

Collection与Collections都属于java.util包下,区别有:

  1. java.util.Collection是一个集合接口。他提供对集合对象进行基本操作的通用接口方法。Collection接口在Java类库中有很多具体的体现。Collection接口的意义是为各种具体的集合提供最大化的统一操作方式。
  2. java.util.Collections是一个包装类。它包含各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类服务于Java的Collection框架。

List与Set之间的区别:

List与Set都属于Collection集合(单个数据值元素的集合),区别有:

List有序,Set无序

List元素可重复,Set元素不可重复

ArrayList与LinkedList,Vector之间的区别:

  1. ArrayList和Vector都是动态数组,区别是ArrayList是线程不安全的,Vector是线程安全的,但ArrayList性能好于Vector。
  2. ArrayList与LinkedList的区别是他们的数据结构不同,ArrayList是动态数组,LinkedList是双向链表,在查询操作较多,在特定的位置插入数据和删除数据较少的情况下一般选用ArrayList,在特定位置插入数据,删除数据操作较多,查询较少的情况下一般选用LinkedList。一般ArrayList应用较多。

ArrayList特点与扩容问题

特点:有序 可重复

可变数组作为底层实现

根据索引做查询效率高

增删效率低,设计到新数组的创建,数据的拷贝等问题

大量做查询,少量做增删的时候适合使用ArrayList

第一次添加数据内部构建数组的初始容量为10

扩容:int newCapacity = oldCapacity + (oldCapacity >> 1);

ArrayList每次扩容原容量的1.5倍。

HashMap扩容机制:

  1. 空参数的构造函数:实例化的HashMap默认内部数组为null,即没有实例化。第一次调用put方法时,则会开始第一次初始化扩容,长度为16。
  2. 有参构造函数:用于指定容量。会根据指定正整数找到不小于指定容量的2的幂数,将这个数设置给阈值。第一次调用put方法时,会将阈值赋值给容量,然后 阈值=容量*负载因子 。
  3. 如果不是第一次扩容,则容量变为原来的两倍,阈值也变为原来的两倍。
  4. 首次put时会触发扩容,然后存入数据,再判断是否需要扩容。
  5. 不是首次put,则直接存入数据(不再初始化),然后判断是否需要扩容。

HashMap线程安全问题

注意,此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;以防止对映射进行意外的非同步访问。

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号