常见问题练习1

20210802练习

编辑时间:2021/08/03

读完本节:大概花费15分钟,共1560词

1.列举java的常用容器(集合)
  1. Java Collection包括List、Set和Map,其中常用的List包括ArrayList、LinkedList、Vector;常用的Set包括HashSet、TreeSet、LinkedHashSet;常用的Map包括HashMap、TreeMap、SortMap、LinkedHashMap、ConcurrentHashMap等。
2.List和Set的区别,不可重复是什么意思?
  1. List可以存放重复的数据,但是Set不能存放可重复的数据;
  2. List存放元素的顺序是有序的,Set存放的数据是无序的;
  3. List不能存放null值,Set可以存放null值;
  4. Set存放的数据不可重复指的是Set底层使用的是Map结构。只不过Set和Map的区别在于Set底层的Entry数组中的value值是null,通过将数据存入key保证不可重复。存入数据的过程中,两个对象通过hashCode()方法比较相等,且两个对象的equals()方法返回值也相等对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象的相等规则。即”相等的对象必须具有相等的散列码
3.HashMap是否线程安全,如果想用线程安全的HashMap怎么做?
  1. HashMap不是线程安全的集合;
  2. 如果像使用线程安全的HashMap可以使用Collections类对HashMap进行加锁,或者改用效率更加高的ConcurrentHashMap
4.编写一个单例模式,常见的单例有哪些,分别列举?
public class SingletonClass{
  /** 枚举单例 */
  public enum Singleton{
  	INSTANCE;
    public Singleton getInstance(){
      return INSTANCE;
    }
  }
}
public class SingletonClass{
  /** 饿汉单例 */
  public class Singleton{
    private Singleton INSTANCE = new Singleton();
    
    private Singleton(){}
    
    public static getInstance(){
    	return INSTANCE;
    }
  }
}
 public class Singleton {
   /*
   * 懒汉单例,双重锁
   * 利用静态变量来记录Singleton的唯一实例
   * volatile 关键字确保:当INSTANCE变量被初始化成Singleton实例时,
   * 多个线程正确地处理INSTANCE变量
   */
	 private volatile static Singleton INSTANCE;
   
	 private Singleton(){}
   
	 public static Singleton getInstance(){
     		if(INSTANCE == null){
          	synchronized(Singleton.class){    //进入同步区域
								if(INSTANCE == null){     //在检查一次,如果为null,则创建
											INSTANCE  = new Singleton();
                }
            }
        }
				return INSTANCE;
		}
}
public class Singleton{
  private static volatile Singleton INSTANCE;
  
  private statci Lock lock = new ReentrantLock();
  
  private Singleton(){}
  
  public static Singleton getInstance(){
    try{
      lock.lock();
      if(INSTANCE == null)
        INSTANCE = new Singleton();
    }catch(){
      e.printStaticTrace();
    }finally{
      lock.unlock();
    }
  }
}
5.有哪些排序算法,写出快速排序算法的实现
  1. 常见算法以及时间复杂度

  2. 冒泡、插入、选择排序

  3. 快速排序Java实现

    public static void quickSort(int[] arr,final int left,final int right) {
    		if (left > right)
    			return;
    		int base = arr[left];
    		int i = left;
    		int j = right;
    		// 不相遇
    		while (i != j) {
    			// 从右边开始找比基准数小的就停下,反言之就是比基准数大或者相等就继续
    			while (arr[j] >= base && i < j) {
    				j--;
    			}
    			while (arr[i] <= base && i < j) {
    				i++;
    			}
          //左边比base大,右边比base小,停下,直接交换左右指针指向的位置
    			int t = arr[i];
    			arr[i] = arr[j];
    			arr[j] = t;
    		}
    		// i=j 相遇位置的数赋值给基准数这个位置的元素
    		arr[left] = arr[i];
    		// 把基准数赋值给相遇位置的数
    		arr[i] = base;
    		quickSort(arr, left, i - 1);
    		quickSort(arr, i + 1, right);
    	}
    
    }
    
6.给一个二叉树,使用递归和非递归完成先序,中序和后序的遍历
//先序遍历
public void preOrder(TreeNode root) {
		if (root == null)
			return;
		System.out.print(root.val + " ");
		preOrder(root.left);
		preOrder(root.right);
	}
public void preOrder1(TreeNode root) {
		Stack<TreeNode> stack=new Stack<>();
		TreeNode currNode=root;
		if(currNode!=null) {
			stack.push(currNode);//根节点入栈
			while(!stack.isEmpty()) {
				currNode=stack.pop();//弹出根节点
				System.out.print(currNode.val+" ");
				if(currNode.right!=null) {//右节点先压入栈
					stack.push(currNode.right);
				}
				if(currNode.left!=null) {
					stack.push(currNode.left);
				}
			}
		}
	}
//中序遍历
public void inOrder(TreeNode root) {
		if (root == null)
			return;
		preOrder(root.left);
		System.out.print(root.val + " ");
		preOrder(root.right);
	}
public void inOrder1(TreeNode root) {
		Stack<TreeNode> stack=new Stack<>();
		TreeNode currNode=root;
		while(currNode!=null||!stack.isEmpty()) {
			//先访问左节点,压入左节点
			while(currNode!=null) {
				stack.push(currNode);
				currNode=currNode.left;
			}
			if(!stack.isEmpty()) {
				currNode=stack.pop();//弹出左节点
				System.out.print(currNode.val+" ");
				currNode=currNode.right;//开始压入右节点
			}
		}
	}


//后序遍历
public void afterOrder(TreeNode root) {
		if (root == null)
			return;
		preOrder(root.left);
		preOrder(root.right);
		System.out.print(root.val + " ");
	}

public void afterOrder1(TreeNode root) {
		Stack<TreeNode> stack1=new Stack<>();
		Stack<TreeNode> stack2=new Stack<>();
		TreeNode currNode=root;
		while(currNode!=null||!stack1.isEmpty()) {
			while(currNode!=null) {
				//使用两个栈在stack2中按照左右顺序入栈
				stack1.push(currNode);
				stack2.push(currNode);
				currNode=currNode.right;
			}
			if(!stack1.isEmpty()) {
				currNode=stack1.pop();//弹出左节点
				currNode=currNode.left;
			}
		}
		while(!stack2.isEmpty()) {
			currNode=stack2.pop();
			System.out.print(currNode.val+" ");
		}
	}

//层序遍历
public void levelOrder(TreeNode root) {
		if (root == null)
			return;
		Queue<TreeNode> q = new LinkedList<>();// 定义一个队列
		q.offer(root);// 存入根节点
		while (!q.isEmpty()) {
			TreeNode temp = q.poll();// 弹出根节点
			System.out.print(temp.val + " ");// 输出根节点
			if (temp.left != null) {// 找到根节点下的左右节点并存入队列
				q.offer(temp.left);
			}
			if (temp.right != null) {
				q.offer(temp.right);
			}
		}
	}
7.数据库的事务的四大特性及数据库的隔离级别

四大特性:原子性、隔离性、一致性、持久性

隔离级别:

​ 读未提交:在一个事务中,读到了其他事务没有提交的数据。会产生数据脏读现象,不能限制不可重复读和幻读。

​ 读已提交:在一个事务中可以读取到其他事务已经提交的数据变化。可防止脏读现象,无法限制不可重复读和幻读。

​ 可重复读:在一个事务中直到事务结束之前,都可以反复的读到事务刚开始看到的数据,并且一直不会发生变化,有效的防止了脏读和不可重复读。

​ 可序列化:只有等一个事务结束,才能进行下一个事务。

8.TCP的三次握手和四次挥手

三次握手四次挥手

9.GET/POST的区别,除了GET/POST还有哪些?

GET和POST发送基于http协议,但是由于服务器的限制,导致两者发送的方式不同

且GET是幂等POST是非幂等可能会修改服务器中的资源请求导致两次结果不同

GET:参数通过URL传输,且会被浏览器主动缓存,传输的非ASCII需要转码

POST:有两个TCP数据包,将参数放置在request body中,缓存需要手动设置,且非ASCII数据通过MIME传输

还有DELETE:删除信息和PUT:添加信息

无限进步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值