输入: 字符串
输出: 去除重复字符并排序的字符串
样例输入: aabceeddf
样例输出: abcdef
合理的表结构对性能的影响至关重要。建表时,定长的字段尽可能放在一张表中,长度不确定的或类型如:text,blob则单独建表,在查询时可提高效率。那何为定长字段和非定长字段呢?
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` char(32) DEFAULT NULL,
`password` char(32) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`introduce` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
上面的表中有五列,分别是id,username,password,birthday,introduce;类型则是有int,char,varchar和date四种。其中id,username,password都给定了初始化长度,当输入的数据小于给定长度则会自动填充,当输入的长度大于给定长度则会自动截取给定的长度,这便是定长字段;而date为时间格式,只能有几个特定的格式,所有不需要设置长度,每种格式都是定长的,一个表中只会用一种格式的时间,所以birthday也是定长字段。
上面表中的introduce列的类型是varchar,虽然给定了初始长度,但当插入的数据长度小于给定的初始长度时,插入多长就存储多长,不会去自动填充;当所插入的字符串超出它的长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误信息,如果是宽松模式,则会截取然后插入 。因此introduce就属于非定长字段。
当一个表中的字段都是定长时,也就意味着该表中的每一条数据也都是长度相同的,在磁盘上存储时所跨的扇区也是一样的,这样我们在查询某一条数据时,只需要跨过一定的扇区拿数据就能得到,显然比一条一条的向下查找效率高得多。
当一个表中既有定长字段又有非定长字段时,该表中每一条数据的长度不再是相同的,在磁盘上存储时所跨的扇区也不再一样,这时我们在查询某一条数据时,只能一条一条的往下查,性能便会大受影响。
因此,出于对性能的考虑,建表时,定长的字段尽可能放在一张表中,长度不确定的单独建表。
var boolean1 = true;
var boolean2 = false;
console.log(typeof boolean1); //boolean
console.log(typeof boolean2); //boolean
虽然Boolean类型的字面值只有两个,但ECMAScript中所有类型的值都有与这两个Boolean值等价的值:
- 任何非零数值都是true,包括正负无穷大,只有0和NaN是false - 任何非空字符串都是true,只有空字符串是false - 任何对象都是true,只有null和undefined是false
var boolean1 = Boolean(0);
console.log(boolean1); //false
var boolean2 = Boolean(1);
console.log(boolean2); //true
var boolean3 = Boolean(-1);
console.log(boolean3); //true
var boolean4 = Boolean("hello");
console.log(boolean4); //true
var boolean5 = Boolean("");
console.log(boolean5); //false
var boolean6 = Boolean(undefined);
console.log(boolean6); //false
var boolean7 = Boolean(null);
console.log(boolean7); //false
利用上面所得到的结论,我们在JS中判断数据是否为空时就会简化,下面是一个简单的演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/login" method="post">
账号:<input type="text" id="username" name="username" value="" />
<br>
密码:<input type="password" id="password" name="password" value="" />
<br>
<input type="button" value="登录" onclick="checklogin()"/>
</form>
<script type="text/javascript">
function checklogin(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
//判断账号是否为空
if(username == ""){
alert("账号不能为空");
return;
}
//判断密码是否为空
if(password == ""){
alert("请输入密码");
return;
}
//提交表单
document.getElementsByTagName("form")[0].submit();
}
</script>
</body>
</html>
上面的JS中的判断可以直接简化:
//判断账号是否为空
if(!username){
alert("账号不能为空");
return;
}
//判断密码是否为空
if(!password){
alert("请输入密码");
return;
}
这样的效果和上面一样,但看起来要相对简单一些。
Java的八大基本数据类型中,float和double可以表示小数,分别叫做单精度浮点数(float)与双精度浮点数(double)。两者有以下区别:
单精度浮点数在机内占4个字节
双精度浮点数在机内占8个字节
单精度浮点数有效数字8位
双精度浮点数有效数字16位
单精度浮点的表示范围:-3.40E+38 ~ +3.40E+38
双精度浮点的表示范围:-1.79E+308 ~ +1.79E+308
两个类型在数据的四则运算中是否会丢失精度呢?
测试代码:
package com.milanuo;
/**
* @author 密拉诺
*/
public class FloatDemo {
public static void main(String[] args) {
float a = 0.15f;
float b = 0.3f;
System.out.println("float的加法运算: " + a + "+" + b + "=" + (float)(a + b));
System.out.println("float的减法运算: " + a + "-" + b + "=" + (float)(a - b));
System.out.println("float的乘法运算: " + a + "*" + b + "=" + (float)(a * b));
System.out.println("float的除法运算: " + a + "/" + b + "=" + (float)(a / b));
}
}
测试结果:
float的加法运算: 0.15+0.3=0.45000002
float的减法运算: 0.15-0.3=-0.15
float的乘法运算: 0.15*0.3=0.045
float的除法运算: 0.15/0.3=0.5
这个结果是不是偶然呢?我们多测试几组数据:
float的加法运算: 2.4+1.2=3.6000001
float的减法运算: 2.4-1.2=1.2
float的乘法运算: 2.4*1.2=2.88
float的除法运算: 2.4/1.2=2.0
float的加法运算: 6.3+3.0=9.3
float的减法运算: 6.3-3.0=3.3000002
float的乘法运算: 6.3*3.0=18.900002
float的除法运算: 6.3/3.0=2.1000001
float的加法运算: 8.4+2.1=10.5
float的减法运算: 8.4-2.1=6.2999997
float的乘法运算: 8.4*2.1=17.639997
float的除法运算: 8.4/2.1=4.0
从上面的测试结果不难看出:
测试代码:
package com.milanuo;
/**
* @author 密拉诺
*/
public class DoubleDemo {
public static void main(String[] args) {
double a = 0.15D;
double b = 0.3D;
System.out.println("double的加法运算: " + a + "+" + b + "=" + (double)(a + b));
System.out.println("double的减法运算: " + a + "-" + b + "=" + (double)(a - b));
System.out.println("double的乘法运算: " + a + "*" + b + "=" + (double)(a * b));
System.out.println("double的除法运算: " + a + "/" + b + "=" + (double)(a / b));
}
}
测试结果:
double的加法运算: 0.15+0.3=0.44999999999999996
double的减法运算: 0.15-0.3=-0.15
double的乘法运算: 0.15*0.3=0.045
double的除法运算: 0.15/0.3=0.5
double的加法运算: 2.4+1.2=3.5999999999999996
double的减法运算: 2.4-1.2=1.2
double的乘法运算: 2.4*1.2=2.88
double的除法运算: 2.4/1.2=2.0
double的加法运算: 6.3+3.0=9.3
double的减法运算: 6.3-3.0=3.3
double的乘法运算: 6.3*3.0=18.9
double的除法运算: 6.3/3.0=2.1
double的加法运算: 8.4+2.1=10.5
double的减法运算: 8.4-2.1=6.300000000000001
double的乘法运算: 8.4*2.1=17.64
double的除法运算: 8.4/2.1=4.0
相同的四组数据,在double类型中与float类型有所不同:
绝大多数现代的计算机系统采纳了所谓的浮点数表达方式。这种表达方式利用科学计数法来表达实数, 即用一个尾数(Mantissa ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。 比如123.45用十进制科学计数法可以表达为1.2345 × 10²,其中1.2345为尾数,10为基数,2为指数。
浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。 因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运算的时候要特别小心。
float和double类型主要是为了科学计算和工程计算而设计的。他们执行二进制浮点运算, 是为了在广泛的数字范围上提供较为精确的快速近似计算而精心设计的。 然而,它们并没有提供完全精确的结果,所以我们不应该用于精确计算的场合。
float和double类型尤其不适合用于货币运算,当我们需要精确的计算或者用于货币运算时,可以使用java.math.BigDecimal。