• Java面试题精选21到31


    21、数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?

    · Array大小是固定的,ArrayList的大小是动态变化的。
    · ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

    22、时间复杂度如何计算

    常见的时间复杂度量级有:

    常数阶O(1)
    线性阶O(n)
    对数阶O(logN)
    线性对数阶O(nlogN)
    平方阶O(n2)
    立方阶O(n3)
    K次方阶O(nk)
    指数阶(2n)
    1、常数阶O(1)
      无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1)。如:

    int i = 1;
    int j = 2;
    ++i;
    j++;
    int m = i + j;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、线性阶O(n)
      代码消耗随着某个变量的增长而增长(for循环)。如:

    for(i=1; i<=n; ++i)
    {
       j = i;
       j++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3、对数阶O(logN)

    int i = 1;
    while(i<n)
    {
        i = i * 2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    从上面代码可以看到,在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。我们试着求解一下,假设循环x次之后,i 就大于 n 了,此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2n
    也就是说当循环 log2n 次以后,这个代码就结束了。因此这个代码的时间复杂度为:O(logn)。

    4、线性对数阶O(nlogN)
      线性对数阶O(nlogN) 其实非常容易理解,将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是了O(nlogN)。如:

    for(m=1; m<n; m++)
    {
        i = 1;
        while(i<n)
        {
            i = i * 2;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5、平方阶O(n²)
      平方阶O(n2)也好理解,把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²) 了。

    for(x=1; i<=n; x++)
    {
       for(i=1; i<=n; i++)
        {
           j = i;
           j++;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6、立方阶O(n³)、K次方阶O(n^k)
      参考上面的O(n²) 去理解,O(n³)相当于三层n循环,其它的类似。

    23、HashSet和TreeSet有什么区别?

    HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
    另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。

    24 、System.gc()和Runtime.gc()会做什么事情?

    这两个方法用来提示JVM要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于JVM的。

    25、String 和StringBuffer的区别

    JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。

    26、说出ArrayList,Vector, LinkedList的存储性能和特性

    ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而 LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

    27、sleep() 和 wait() 有什么区别?

    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
    wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

    28 、short s1 = 1; s1 = s1 + 1;有什么错?short s1 = 1; s1 += 1;有什么错?

    第一题:short s1 = 1; s1 = s1 + 1;

    错! s1 + 1,s1是short类型,1是int型,s1会自动转换为int型的1,与1相加后,得到int型的2,要向左侧的short类型的s1看齐,即需要通过强制类型转换。正确写法:s1 = (short) (s1 + 1);

    第二题:short s1 = 1; s1 += 1;

    正确! 执行s1+=1;其实执行的是s1 = (short) (s1 + 1); 其中会有一个强制转换的过程。

    29 、编程题: 写一个Singleton出来。

    Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
    一般Singleton模式通常有几种种形式:
    第一种形式:
    定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInsta nce方法获取对它的引用,继而调用其中的方法。

    public class Singleton { 
        private Singleton(){} 
    
       //在自己内部定义自己一个实例,是不是很奇怪?
       //注意这是private 只供内部调用
       private static Singleton instance = new Singleton(); 
    
       //这里提供了一个供外部访问本class的静态方法,可以直接访问
       public static Singleton getInstance() { 
         return instance; 
       } 
    
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第二种形式:

    public class Singleton { 
      private static Singleton instance = null; 
      public static synchronized Singleton getInstance() { 
      //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
    
    //使用时生成实例,提高了效率!
    if (instance==null) {
         instance=new Singleton(); 
         return instance; 
      } 
    }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    30、请说出你所知道的线程同步的方法。

    wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
    sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
    notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
    Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

    31、简述synchronized和java.util.concurrent.locks.Lock的异同?

    主要相同点:Lock能完成synchronized所实现的所有功能
    主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。

  • 相关阅读:
    Vue3+vite 添加router后的2个坑
    LeetCode 847. Shortest Path Visiting All Nodes【状态压缩,BFS;动态规划,最短路】2200
    构建未来:利用服务器打造个性化创意项目和在线社区
    AI:141-利用自然语言处理改进医疗信息提取与分类
    【AI 编程助手】DevChat 解析:深入了解、快速配置与实际操作案例的完整指南
    MATLAB 2022b 中设置关闭 MATLAB 之前进行询问
    Springboot集成Quartz
    宝塔显示100%负载100%cpu解决办法
    java Spring Boot2.7实现一个简单的爬虫功能
    LeetCode 2525. 根据规则将箱子分类【模拟】1301
  • 原文地址:https://blog.csdn.net/weixin_42435657/article/details/127106177