hashMap原理
hashMap是数组+链表的数据结构 每一个数组元素中都是一个链表 通过记录的关键字key.hashCode()%数组的长度 来决定记录在数组中的存储位置 对于数组的同一个存储位置,后来的元素永远放在链表的表头
HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来 储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 Ha shMap在每个链表节点中储存键值对对象。
当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。
因为HashMap的好处非常多,我曾经在电子商务的应用中使用HashMap作为缓存。因为金融领域非常多的运用Java,也出于性能的考虑,我们会经常用到HashMap和ConcurrentHashMap。
饿汉式单例
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; }
懒汉式单例
public class Singleton { private static Singleton instance = null; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
内部类
public class Singleton { private Singleton() {} public static Singleton getInstance() { return SingletonHold.INSTANCE; } private static class SingletonHold { private static final Singleton INSTANCE = new Singleton(); } }
Java中HashMap遍历的四种方式
第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); Object val = entry.getValue(); } 效率高,以后一定要使用此种方式! 第二种: Map map = new HashMap(); Iterator iter = map.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); Object val = map.get(key); } 效率低,以后尽量少使用!
1. Map的四种遍历方式
下面只是简单介绍各种遍历示例(以HashMap为例),各自优劣会在本文后面进行分析给出结论。
(1) for each map.entrySet() Map<String, String> map = new HashMap<String, String>(); for (Entry<String, String> entry : map.entrySet()) { entry.getKey(); entry.getValue(); } (2) 显示调用map.entrySet()的集合迭代器 Iterator<Map.Entry<String,String>>iterator=map.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry<String,String>entry=iterator.next(); entry.getKey(); entry.getValue(); } (3) for each map.keySet(),再调用get获取 Map<String, String> map = new HashMap<String, String>(); for (String key : map.keySet()) { map.get(key); } (4) for each map.entrySet(),用临时变量保存map.entrySet() Set<Entry<String,String>>entrySet=map.entrySet(); for(Entry<String,String>entry:entrySet){ entry.getKey(); entry.getValue(); }
对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。而entryset只是遍历了第一次,他把key和value都放到了entry中,所以就快了。
jdk1.8新特性
速度更快 – 红黑树
代码更少 – Lambda
强大的Stream API – Stream
便于并行 – Parallel
最大化减少空指针异常 – Optional
spring IOC和AOP的原理?
IOC:控制反转也叫依赖注入。利用了工厂模式
将对象交给容器管理,你只需要在spring配置文件中配置对应的bean以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,
spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类(假设这个类名是A),
分配的方法就是调用A的setter方法来注入,而不需要你在A里面new这些bean了。
AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,
用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。
也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。
日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码
MySQL数据库的四种索引类型
索引类型主要包括:普通索引,唯一索引,主键索引和组合索引。 (1)普通索引,就是直接创建简单的索引。CREATE INDEX indexName ON mytable(username(length)); (2)唯一索引,与普通索引类似,不同的是,Mysql的索引列值必须唯一,但允许有空值。如果是组合索引,
则列值的组合必须唯一。有以下几种创建方式:CTEATE UNIQUE INDEX indexName ON mytable(username(length))修改表结构; ALTER mytable ADD UNIQUE [indexName] ON (username(length))创建表的时候直接指定。 (3)主键索引,它是一种特殊的唯一索引,不允许有空值,一般是在建表的时候同时创建主键索引。 CREATE TABLE mytable(ID INT NOT NULL,username VARCHAR(16) NOT NULL,PRIMARY KEY(ID)); 当然也可以用ALTER命令,记住:一个表只能有一个主键。 (4)组合索引, CTEATE TABLE mytable(ID INT NOT NULL,username VARCHAR(16) NOT NULL,city VARCHAR(50) NOT NULL,age INT NOT NULL);
乐观锁和悲观锁是两种思想
乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:
如果别人修改了数据则放弃操作,否则执行操作。
悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
线程池的几种方式
newFixedThreadPool(int nThreads) 创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程 newCachedThreadPool() 创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制 newSingleThreadExecutor() 这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行 newScheduledThreadPool(int corePoolSize) 创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
Spring MVC的优点
它是基于组件技术的.全部的应用对象,无论控制器和视图,还是业务对象之类的都是 java组件.并且和Spring提供的其他基础结构紧密集成. 不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的) 可以任意使用各种视图技术,而不仅仅局限于JSP 支持各种请求资源的映射策略 它应是易于扩展的
springMVC的原理
客户端发送请求到DispatcherServlet
DispatcherServlet查询handlerMapping找到处理请求的Controller
Controller调用业务逻辑后,返回ModelAndView
DispatcherServlet查询ModelAndView,找到指定视图
视图将结果返回到客户端