美文网首页
【JAVA】面试-基础篇

【JAVA】面试-基础篇

作者: Y了个J | 来源:发表于2019-05-19 15:43 被阅读0次

集合框架

面试题:你说说collection里面有什么子类。
其实面试的时候听到这个问题的时候,你要知道,面试官是想考察List,Set,Queue,Stack
list和set是实现了collection接口的。

list

1.可以允许重复的对象
2.可以插入多个null元素。
3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList适合做查询,而 LinkedList适合做增删。

ArrayList、LinkedList、Vector的区别

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

set:

1.不允许重复对象
2.无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
3.只允许一个 null 元素
4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。


Map

1.Map不是collection的子接口或者实现类。Map是一个接口。
2.Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
3.TreeMap 也通过 Comparator 或者 Comparable 维护了一个排序顺序。
4.Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
5.Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)


基于 HashMap 实现的 HashSet底层原理

list在foreach循环中进行元素remove/add操作,会抛ConcurrentModificationException 异常

十亿条淘宝购买记录,怎么获取出现最多的前十个

filter和iterceptor的区别

100个有序的整型,如何打乱顺序?

linux命令

jps -l 或 ps aux|grep java 查看java进程
ps aux 查看所有进程
ps –ef|grep tomcat 查看所有有关tomcat的进程
ps -ef|grep --color java 高亮要查询的关键字
kill -9 19979 终止线程号位19979的进程


说一下Innodb和MySIAM的区别

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外部键等高级数据库功能。
MySIAM支持表锁,Innodb支持表锁行锁。


什么情况会造成内存泄漏

首先,这些对象是可达的,存在通路可以与其相连;
其次,这些对象是无用的,即程序以后不会再使用这些对象。
如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
ThreadLocal容易造成内存泄漏


什么是线程死锁,如何解决 产生死锁的条件有四个:

1.互斥条件:所谓互斥就是进程在某一时间内独占资源。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

线程死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。

要解决死锁,可以从死锁的四个条件出发,只要破坏了一个必要条件,那么我们的死锁就解决了。在java中使用多线程的时候一定要考虑是否有死锁的问题哦。
1)加锁顺序(线程按照一定的顺序加锁)
2)加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)


红黑树是什么?怎么实现?时间复杂度

红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键值,小于等于右孩子的键值。 除了具备该特性之外,红黑树还包括许多额外的信息。

红黑树的每个节点上都有存储位表示节点的颜色,颜色是红(Red)或黑(Black)。 红黑树的特性:
(1) 每个节点或者是黑色,或者是红色。
(2) 根节点是黑色。
(3) 每个叶子节点是黑色。
(4) 如果一个节点是红色的,则它的子节点必须是黑色的。
(5) 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

具体实现代码这里不贴了,要实现起来,需要包含的基本操作是添加、删除和旋转。在对红黑树进行添加或删除后,会用到旋转方法。旋转的目的是让树保持红黑树的特性。旋转包括两种:左旋、右旋、变色。

红黑树的应用比较广泛,主要是用它来存储有序的数据,它的查找、插入和删除操作的时间复杂度是O(lgn)。


Map、Set、List、Queue、Stack的特点与用法
map在for循环状态下使用remove()为何会抛出异常

异常的分类及处理,结合aop
面向对象的五大职责
结合项目或者某些源码进行描述
classloader的加载机制
重写equals时为何要重写hashcode(),不重写会出现什么问题
java基础类型的向上转型,丢失精度问题
String类为何是不可变的,string的equals方法是如何实现的?
接口与抽象类的区别,为何要这样设计?
重载与重写
IO的优化,NIO
Object有哪些通用方法?
String、StringBuffer与StringBuilder的区别
一致性hash
Java对象的生命周期

多线程与并发

多线程环境下让3个线程依次按顺序执行,如何实现?

// 创建只有一个线程的线程池,能达到排队效果
private static ExecutorService executorService = Executors.newSingleThreadExecutor();

static Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("111111111");
        }
});

static Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("222222222");
        }
});

static Thread thread3 = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("333333333");
        }
});

public static void main(String[] args) throws InterruptedException {
        executorService.submit(thread1);
        executorService.submit(thread2);
        executorService.submit(thread3);
        executorService.shutdown();
    }

创建线程的几种方式,应用场景?
继承thread类,实现runnable或者callable接口

用 wait-notify 写一段代码来解决生产者-消费者问题?

public class Consumer implements Runnable {

    private ProducerTest res;

    Consumer(ProducerTest res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            res.out();
        }
    }
}

public class Producer implements Runnable{

    private ProducerTest res;

    Producer(ProducerTest res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            res.set("商品");
        }
    }
}

public class ProducerTest {

    private String name;

    private int count = 1;

    private boolean flag = false;

    public synchronized void set(String name) {
        //生产资源
        while (flag) {
            try {
                //线程等待。消费者消费资源
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        this.name = name + "---" + count++;
        System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
        flag = true;
        //唤醒等待中的消费者
        this.notifyAll();
    }

    public synchronized void out() {
        //消费资源
        while (!flag) {
            //线程等待,生产者生产资源
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "...消费者..." + this.name);
        flag = false;
        //唤醒生产者,生产资源
        this.notifyAll();
    }

    public static void main(String[] args) {
        ProducerTest r = new ProducerTest();

        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);

        t1.start();
        t2.start();
    }
}

用java写一个线程安全的单例模式

// 饿汉式:
public class Singleton {
    // 直接创建对象
    private static Singleton instance = new Singleton();

    // 私有化构造函数
    private Singleton() {
    }

    // 返回对象实例
    public static Singleton getInstance() {
        return instance;
    }
}

//懒汉式-双重检测
public class Singleton2 {
    // 声明变量
    private static volatile Singleton2 singleton2 = null;

    // 私有化构造函数
    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        if (singleton2 == null) {
            synchronized (Singleton2.class) {
                if (singleton2 == null) {
                    singleton2 = new Singleton2();
                }
            }
        }
        return singleton2;
    }
}

// 工厂模式
Public interface IFactory{ 
  public IProduct createProduct();
} 

Public Class Factory implements IFactory{ 
  public IProduct createProduct(){
    return new Product();
  }
} 

Public class client{ 
    Public Static void main (String [] args){
        IFactory factory=new Factory(); 
        IProduct product=factory.createProduct(); 
        product.ProductMethod();
    }
}

i++ 操作在多线程环境下会出现什么问题?怎么解决?
考虑使用AtomicInteger等相关的类

可重入锁是什么,有哪些?
同步方法与同步代码块,有何区别,使用场景?
同步代码块中抛出异常会发生什么?

同步类容器和并发类容器有何区别,使用场景分别是?
CyclicBarrier 和 CountDownLatch 有什么不同?

java内存模型
线程优化的方案
可以参考cow模式,以及concurrenthashmap的优化锁力度等方面入手

多线程的设计模式

设计一个高并发的系统,需要考虑哪些点?
什么是线程池,你在项目中使用过哪些?
线程池的几种方式要记清楚,底层使用的都是同一个构造方法,要清楚的知道每个参数的含义,线程池大小的优化,从io密集型和计算密集型方面去回答
线程池中任务满了,会怎么处理?
什么是阻塞式方法,自己去设计一个该怎么实现?
CountDownLatch
队列(有界和无界)如何实现?

两个有序的数组合并成一个数组,写代码实现?
给两个数组分别定义一个下标,最大长度是数组长度减一,按位循环比较两个数组,较小元素的
放入新数组,下标加一(注意,较大元素对应的下标不加一),直到某一个下标超过数组长度时
退出循环,此时较短数组已经全部放入新数组,较长数组还有部分剩余,最后将剩下的部分元素
放入新数组,大功告成。

反转一个链表
斐波那契数列
两种方式实现,递归和非递归

树相关的数据结构
此处会问二叉树,排序树,avl树,红黑树,B树,B+树等相关的应用场景

各种排序算法需要简单了解下
冒泡,快速排序,堆排序,二分法等等相关的都需要了解下

相关文章

网友评论

      本文标题:【JAVA】面试-基础篇

      本文链接:https://www.haomeiwen.com/subject/taifzqtx.html