java面试问题

84 阅读5分钟

1.hashmap和hashtable的区别

1.HashMap线程不安全,HashTable线程安全。在hashmap的put方法调用addEntry()方法,假如A线程和B线程同时对同一个数组位置调用addEntry,两个线程会同时得到现在的头结点,然后A写入新的头结点之后,B也写入新的头结点,那B的写入操作就会覆盖A的写入操作造成A的写入操作丢失。

2.hashmap的键值可以为空,HashTable不可为空

3.HashMap继承自AbstractMap类。但二者都实现了Map接口。 Hashtable继承自Dictionary类,Dictionary类是一个已经被废弃的类(见其源码中的注释)。父类都被废弃,自然而然也没人用它的子类Hashtable了。

4.扩容方式不同,HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。 Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。 Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。

5.包含的contains方法不同 HashMap是没有contains方法的,而包括containsValue和containsKey方法;hashtable则保留了contains方法,效果同containsValue,还包括containsValue和containsKey方法。

6.解决hash冲突的方式不同 hashmap用到了数组,链表加红黑树

2.讲一下是springboot(ioc和aop)

3.arraylist和linkedlist的区别

请看6

4.多线程中run和start的区别

run只是一个普通的方法,并不会启动线程,start会启动线程,把方法交给jvm调度

5.讲一下对多线程的理解

6.spring的注入方式

www.iteye.com/blog/blessh…

自动装配(注解形式)

@Autowired是由org.springframework.beans.factory.annotation.Autowired提供,换句话说就是由Spring提供;

public class UserService {
    @Autowired
    private UserDao userDao; 
}

@Autowired只按照byType 注入;如上代码所示,这样装配回去spring容器中找到类型为UserDao的类,然后将其注入进来。这样会产生一个问题,当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候我们需要配合着@Qualifier使用。

@Resource是由javax.annotation.Resource提供,即J2EE提供,需要JDK1.6及以上。

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常    2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常

 3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常

 4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

set方法

在要调用spring管理的对象的类里面要

package com.bless.springdemo.action;  
public class SpringAction {  
        //注入对象springDao  
    private SpringDao springDao;  
        //一定要写被注入对象的set方法  
        public void setSpringDao(SpringDao springDao) {  
        this.springDao = springDao;  
    }  
  
        public void ok(){  
        springDao.ok();  
    }  
}  
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(1)依赖注入,配置当前类中相应的属性-->  
        <property name="springDao" ref="springDao"></property>  
    </bean>  
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  

构造器

public class SpringAction {  
    //注入对象springDao  
    private SpringDao springDao;  
    private User user;  
      
    public SpringAction(SpringDao springDao,User user){  
        this.springDao = springDao;  
        this.user = user;  
        System.out.println("构造方法调用springDao和user");  
    }  
          
        public void save(){  
        user.setName("卡卡");  
        springDao.save(user);  
    }  
}
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->  
        <constructor-arg ref="springDao"></constructor-arg>  
        <constructor-arg ref="user"></constructor-arg>  
    </bean>  
        <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
         <bean name="user" class="com.bless.springdemo.vo.User"></bean>  

静态工厂

 public class SpringAction {  
        //注入对象  
    private FactoryDao staticFactoryDao;  
      
    public void staticFactoryOk(){  
        staticFactoryDao.saveFactory();  
    }  
    //注入对象的set方法  
    public void setStaticFactoryDao(FactoryDao staticFactoryDao) {  
        this.staticFactoryDao = staticFactoryDao;  
    }  
}  
package com.bless.springdemo.factory;  
  
import com.bless.springdemo.dao.FactoryDao;  
import com.bless.springdemo.dao.impl.FactoryDaoImpl;  
import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;  
  
public class DaoFactory {  
    //静态工厂  
    public static final FactoryDao getStaticFactoryDaoImpl(){  
        return new StaticFacotryDaoImpl();  
    }  
}  
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction" >  
        <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->  
        <property name="staticFactoryDao" ref="staticFactoryDao"></property>  
                </property>  
    </bean>  
    <!--(3)此处获取对象的方式是从工厂类中获取静态方法-->  
    <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>  

实例工厂

public class DaoFactory {  
    //实例工厂  
    public FactoryDao getFactoryDaoImpl(){  
        return new FactoryDaoImpl();  
    }  
} 
public class SpringAction {  
    //注入对象  
    private FactoryDao factoryDao;  
      
    public void factoryOk(){  
        factoryDao.saveFactory();  
    }  
  
    public void setFactoryDao(FactoryDao factoryDao) {  
        this.factoryDao = factoryDao;  
    }  
}  
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->  
        <property name="factoryDao" ref="factoryDao"></property>  
    </bean>  
      
    <!--(4)此处获取对象的方式是从工厂类中获取实例方法-->  
    <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>  
    <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>  

7.linux下项目的部署

和windows没啥区别,把war包放在tomcat的wedapp下,在bin目录启动start.sh

8.arraylist是不是线程安全的

www.cnblogs.com/lingshang/p… 这篇可以看下,主要讲了

arraylist的扩容机制?

总的来说就是分两步: 1、扩容把原来的数组复制到另一个内存空间更大的数组中 2、添加元素把新元素添加到扩容以后的数组中

private static final int DEFAULT_CAPACITY = 10; if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } 如果在添加的时候远数组是空的,就直接给一个10的长度 int newCapacity = oldCapacity + (oldCapacity >> 1); oldCapacity >> 1 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍 elementData = Arrays.copyOf(elementData, newCapacity); 将原数组拷贝到你自己定义的数组里,而且可以选择拷贝的起点和长度以及放入新数组中的位置

arrayrrlist扩容导致性能的下降如何解决?

用有参构造方法直接指定长度 ArrayList objects = new ArrayList<>(1000);

arraylist插入或删除的元素一定比linkedlist慢吗?

不一定,因为在都要遍历node节点

arraylist是不是线程安全的?

不是线程安全的,java.util.ArrayList 中的 add(E e) 方法里有 size++ 的操作,而 size++ 并不是原子操作,所以如果在 size++ 的过程中,其他线程被调度,并且也去操作同一个 ArrayList,那么 size 的值就可能不准确了。可以用vector或者public static List arrayList = Collections.synchronizedList(new ArrayList());来解决,他们都是线程同步的

怎么把两个arraylist相加?

addAll方法

arraylist和linkedList的区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous)

2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

时间复杂度比较:

首先一点关键的是,ArrayList的内部实现是基于基础的对象数组的,因此,它使用get方法访问列表中的任意一个元素时(random access),它的速度要比LinkedList快(O1)。LinkedList中的get方法是按照顺序从列表的一端开始检查,直到另外一端(On)。对LinkedList而言,访问列表中的某个指定元素没有更快的方法了

但在某些情况下LinkedList的表现要优于ArrayList,有些算法在LinkedList中实现时效率更高。比方说,利用Collections.reverse方法对列表进行反转时,其性能就要好些。当要对list进行大量的插入和删除操作时,LinkedList也是一个较好的选择。