主要原因是默认从Object继承来的hashCode是基于对象的ID实现的。
如果你重写了equals,比如说是基于对象的内容实现的,而保留hashCode的实现不变,那么很可能某两个对象明明是“相等”,而hashCode却不一样。
这样,当你用其中的一个作为键保存到hashMap、hasoTable或hashSet中,再以“相等的”找另一个作为键值去查找他们的时候,则根本找不到。
底层是数组+链表+红黑树,哈希表
key : value结构,key不可重复,重复则value值被覆盖
HashMap的key会先后调用hashCode and equals方法,两个方法都需要重写
map.put(k,v)、map.get(k)实现原理:
调用k的hashCode()方法,找到数组下标,再与链表上元素进行equals()。
单向链表中元素超过8个,那么单向链表这种数据结构会变成红黑树数据结构。
当红黑树上的节点数量小于6个,会重新把红黑树变成单向链表数据结构。
hashmap集合的默认初始化容量为16,默认加载因子为0.75,当hashMap集合底层数组的容量达到75%时,数组就开始扩容。
默认的equals方法同==对于值对象,==比较的是两个对象的值对于引用对象,比较的是两个对象的地址 map遍历
keySet().iterator();
entrySet().iterator();
substring截取字符串substring(2); [2,结束]
substring(2,4); [2,4)
为什么左含右不含
String st1 = "abcdefghi"; String st2 = "ss"; st1.substring(0,st2.length()); //返回"ab" //length值比索引值多1,右不含正好
concat(“拼接字符串”);
contains(“包含字符串”)
JDBCClass.forName(“com.mysql.jdbc.Driver”):加载注册驱动
DriverManager驱动:获取连接,返回一个连接
Connection对象:连接
Statement对象:执行SQL
ResultSet对象:结果集
事务
DML(Data Manipulation Language)数据 *** 纵语言:对数据进行 *** 作
select、insert、delete、update
DDL(Data Definition Language)数据库定义语言:
改变表(table)结构,对对象进行处理,表、视图、索引、存储组(STOGROUP)
create(创建)、alter(修改)、drop(删除)
DCL(Data Control Language) 数据库控制语言:设置或更改数据库用户或角色权限
grant(授予权限)、deny、revoke
数据一旦提交,不可回滚
DML、DDL一旦执行,自动提交
set autocommit = false; //可取消DML *** 作自动提交,对DDL无效
connection.setAutoCommit(false);
默认再关闭连接时,自动提交数据
connection.close();
原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) 隔离级别
并发问题
脏读:T1读取了T2更新但没有提交的数据
不可重复读:T1读取数据,T2更新数据,T1再读,两次数据不一致
幻读:T1读取数据,T2插入数据,T1再读,数据不一致,多出几行
隔离级别
read uncommitted(读未提交)read committed(读已提交):oracle默认
解决脏读
在一个事务内,其他用户 *** 作数据库且提交了,自己会读到修改后的数据repeatable read(可重复读):mysql默认
解决不可重复读
在一个事务内,其他用户 *** 作数据库不影响 自己读取数据,事务未提交期间数据不会改变serializable(串行化):解决幻读
SQL
更新:修改现有行
UPDATE 表名称 SET 列名称=新值,列名称=新值 WHERe 列名称=某值 update user set name='jack' where id=1;
插入:创建新行
INSERT INTO 表名称 VALUES (值1, 值2,....) INSERT INTO 表名称 (列1, 列2,...) VALUES (值1, 值2,....) INSERT INTO user VALUES("jack",12,"男"); INSERT INTO user(name,a) VALUES("jack",12,"男");
删除
DELETE FROM 表名称 WHERe 列名称 = 值HashMap和Hashtable的区别
HashMap不是线程安全的,HashMap允许null key和null value,而hashtable不允许。效率高一点。
HashTable是线程安全
sleep与wait的区别 1、来自不同的类sleep来自Thread类,和wait来自Object类。
2、有没有释放锁(释放资源)sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。
最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源
就是说sleep有时间限制的就像闹钟一样到时候就叫了,而wait是无限期的除非用户主动notify
3、使用范围不同wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
4、是否需要捕获异常sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
sleep()方法和yield()方法有什么区别?①sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
④ sleep()方法比yield()方法(跟 *** 作系统CPU调度相关)具有更好的可移植性。
在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
t.join(); //调用join方法,等待线程t执行完毕
t.join(1000); //等待 t 线程,等待时间是1000毫秒。
final修饰属性
基本类型:值不变对象:引用不变
final修饰方法:不可重写
final修饰类:不可继承
final修饰基本类型变量和引用变量当使用final修饰基本数据类型时,不能对其重新赋值,不能被改变。当使用final修饰引用类型变量时,它仅仅保证他的地址不变,即一直引用同一个对象,但这个对象完全可以发生改变。 static
static修饰方法:
static静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
static修饰变量:
静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
static修饰内部类:
1.静态内部类跟静态方法一样,只能访问静态的成员变量和方法,不能访问非静态的方法和属性,但是普通内部类可以访问任意外部类的成员变量和方法
2.静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。
3.静态内部类可以单独初始化:
Inner i = new Outer.Inner();
普通内部类初始化:
Outer o = new Outer();
Inner i = o.new Inner();
存储位置不同、安全性不同、存储方向不同、跨域支持不同、依赖条件不同、大小不同。
1、存储位置不同,session 在服务器端,cookie 在客户端(浏览器)
2、安全性不同,cookie存放在客户端,可通过xss漏洞进行攻击,获取用户敏感信息,session 默认被存在在服务器的一个文件里,不容易被获取。
3、存储方向不同,session 可以放在文件、数据库、或内存中都可以。
4、跨域支持不同,cookie支持跨域使用,session只有在同一个站点才能使用。
5、依赖条件不同、session 的运行依赖 session id,而 session id 是存在 cookie 中的,如果浏览器禁用了 cookie ,同时 session 也会失效
6、大小不同,cookie的大小限制为4kB,且一般一个站点只能用20个cookie。
7、session id是维持一个会话的核心就是客户端的唯一标识。
session的创建:当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了sessionId,如果已包含则说明以前已经为此客户端创建过session,服务
器就按照sessionId把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关
联的sessionId,sessionId的值是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。
servlet生命周期1,创建Servlet对象,调用构造函数,通过服务器反射机制创建Servlet对象,第一次请求时才会创建。(默认)
2,调用Servlet对象的init()方法,初始化Servlet的信息,init()方法只会在创建后被调用一次(初始化阶段)
3,响应请求,调用service()或者是doGet(),doPost()方法来处理请求,这些方法是运行的在多线程状态下的。(响应客户请求阶段)
4, 在长时间没有被调用或者是服务器关闭时,会调用destroy()方法来销毁Servlet对象。(终止阶段)
反射获取对象三种方式:
1、Class clazz1 = Class.forName(“全限定类名”);
2、Class clazz2 = Person.class;
3、Person p = new Preson(); Class clazz3 = p.getClass();
获取构造器
Construnctor con = clazz1.getConstructor(int.class,String.Class);
通过构造器获取对象
User user = (User)con.newInstance(12,“小明”);
获取成员变量并使用—Filed对象
Class.getField(String) 获取类中可见字段
getDeclaedField(“name”) 获取私有变量 setAccessible(true)
获得方法并使用 Method
Class.getMethod(String, Class…)
Class.getDeclaredMethod(String, Class…)
获得该类的所有接口
Class[] getInterfaces();
SQLleft join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 ,没有显示null
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录,没有显示null
inner join(等值连接) 只返回两个表中联结字段相等的行
异常小、访问大
io流继承关系
InputStream:读取字节流抽象类
FileInputStream:字节输入流FilterInputstream:过滤字节输入流
BufferedInputStream:字节输入缓冲流DataInputStream:数据类型输入处理流 ObjectInputStream:引用类型输入处理流(对象反序列化)ByteArrayInputStream:字节数组输入流
Reader:读取字符流抽象类
InputStreamReader:字符输入处理流,字节流–>字符流
FileReader:字符输入流 BufferedReader:字符输入缓冲流CharArrayReader:字符数组输入流 Array与Arraylist区别
Array:固定长度数组,存储相同类型的基本数据类型或对象
ArrayList:动态数组,可存储不同类型对象,基本数据类型通过自动装拆箱转换为对象
储存的数据类型ArrayList可以存储不同类型的对象,而Array只能存储相同数据类型的数据。
长度的可变Array的长度实际上是不可变的,二维变长数组实际上的长度也是固定的,可变的只是其中元素的长度。ArrayList的长度既可以指定(即使指定了长度,也会自动2倍扩容)也可以不指定,是变长的。
存取和增删元素对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的 *** 作,频繁的 *** 作可能会影响一部分效率。
转换list.toArray()
Arrays.asList()
String、StringBuffer、StringBuilder 创建String str1 = "hello world"; //字面量创建,添加到常量池
String str1 = new String("hello world"); //在类加载的过程中,在运行时常量池中创建了一个"abc"对象,在代码执行过程中创建了一个String对象。修改
public final class String{ } //String类被final修饰,不可继承
private final char value[]; //value属性被final修饰,不可更改
对String对象的任何改变都不影响到原对象,相关的任何change *** 作都会生成新的对象。
String string = ""; string += "hello"; //String类执行+= *** 作,底层创建StringBuilder进行添加
JVM自动优化为StringBuilder
StringBuilder str = new StringBuilder(string); str.append("hello"); str.toString();
StringBuffer、StringBuilder会直接在原对象上添加元素
StringBuffer加锁,比StringBuilder慢
值传递与引用传递值传递:(形式参数类型是基本数据类型):
方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
引用传递:(形式参数类型是引用数据类型参数):
也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的 *** 作实际上就是对实际参数的 *** 作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
数据库范式1.第一范式(确保每列保持原子性)
2.第二范式(确保表中的每列都和主键相关)
3.第三范式(确保每列都和主键列直接相关,而不是间接相关,消除依赖)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)