Java架构师成长之道之Java数据计算

Java架构师成长之道

3.1 Java数据计算概述

计算机最主要的任务就是完成生产生活中的各种数据的运算,在Java中提供了诸多的运算符来完成相关数据的运算,在日常程序开发中最常用的有算术运算符、自增运算符、关系运算符、逻辑运算符以及三目运算符,在JDK源码中会使用到基于二进制的位运算符。

在了解具体运算符的使用之前,先了解关于数据计算的几个概念

package net.ittimeline.java.core.operator;
import static java.lang.System.out;
/*** 数据计算的相关概念* 运算符:数据执行的运算类型,例如算术、逻辑、关系、位运算* 操作数:参与运算的数据,例如2,(3+2)都是操作数* 表达式:由操作数和运算符组成,通常是完成某种业务数据计算而设计的,例如计算圆的面积* 优先级:在各种运算符参与运算时,有不同的执行顺序,由它们的优先级决定,可以使用()改变优先级* 结合性:执行运算的方向,例如从左到右或者从右到左* @author liuguanglei 18601767221@163.com* @create 2019-07-30 11:51* @website www.ittimeline.net* @since JDK11.03*/
public class OperatorConceptTest {public static void main(String[] args) {// 3+5就是表达式,3,5就是操作数int result=3+5;System.out.println("result ="+result);/*** 算术运算的优先级是先乘除后加减* 可以使用()改变优先级*/int precedence=(45+5)/5*10;out.println("precedence = "+precedence);}
}

  • 运算符:指定数据执行的运算类型,例如算术,逻辑,关系,比较,位运算等等

  • 操作数:就是参与运算的数据,例如2,(3+2)都是一个操作数

  • 表达式:由操作数和运算符组成,通常都是完成某种业务数据计算而设计的,例如计算圆的面积等等。

  • 优先级:在各种运算符参与运算时,有不同的执行顺序,由它们的优先级决定,可以使用()来改变执行的顺序

  • 结合性:执行计算的方向,一般是从左到右,但是赋值运算是从右到左。

3.2 算术运算符

算术运算就是数学意义上的加减乘除以及取模运算,Java中支持的算术运算符包含加法(+)、减法(-)、乘法(*)、除法(/)、和取模(/)

  • 算术运算符的优先级是先乘除,后加减。
  • 算术运算符的结合性是从左到右
  • 算术运算计算结果的类型是参与运算的最大数据类型,例如整数和浮点数运算的结果是浮点型
  • 赋值(=)时会进行自动类型转换

算术运算案例

package net.ittimeline.java.core.operator.arithmetic;/*** 算术运算符* Java中的算术运算符支持数学意义的+ - * /以及取模(%)运算(求余数)** @author liuguanglei 18601767221@163.com* @create 2019-07-28 09:40* @website www.ittimeline.net* @since JDK11.03*/
public class ArithmeticDivideTest {/*** 除法运算* @param args*/public static void main(String[] args) {//算术计算的结果的数据类型是参与运算的最大数据类型int source=12;int target=5;//int和int运算的结果是intint result=source/target;System.out.println("result = "+result);//算术运算符结合性是从左向右运算result=source/target*target;//result=10System.out.println("result = "+result);//赋值时会执行自动类型转换double dblResult=source/target;//运算结果是2.0System.out.println("dblResult ="+dblResult);//double和int运算结果是double//通过强制类型转换将int转换为doubledblResult=(double) source/target;//获取精确的运行结果System.out.println("dblResult ="+dblResult);}
}

取模运算是求余数,开发中通常用于判断数据是否能够整除。取模也会作为数据库中间件MyCAT,ShardingJDBC实现取模算法。

  • 取模运算结果的符号类型(正负)和被模数一致
  • 整数和浮点数可以进行取模运算
package net.ittimeline.java.core.operator.arithmetic;/*** 取模(求余数)运算* 开发中经常用取模运算符(%)来判断数据是否能够整除的情况** @author liuguanglei 18601767221@163.com* @create 2019-07-28 09:49* @website www.ittimeline.net* @since JDK11.03*/
public class ArithmeticRemainderTest {/*** 求余数** @param args*/public static void main(String[] args) {int source = 12;int target = 5;int result = source % target;//12/5=2..2 即余数的结果就是2System.out.println("result = " + result);//运算结果表明求余数结果的符号和被余数相同source = -12;result = source % target;System.out.println("result = " + result);source = 12;target = -5;result = source % target;System.out.println("result =" + result);double dblSource = 12.5;double dblTarget = 5.0;double dblResult = dblSource % dblTarget;//浮点数也可以取模System.out.println("dblResult = " + dblResult);}
}

取模运算应用案例:将五位整数反转

package net.ittimeline.java.core.operator.arithmetic;/*** 取模运算案例* 将一个五位整数反转* 例如12345变成54321* @author liuguanglei 18601767221@163.com* @create 2019-08-03 09:39* @website www.ittimeline.net* @since JDK11.03*/
public class ArithmeticRemainderApp {public static void main(String[] args) {int number=12345;System.out.println("反转之前的五位整数是"+number);//首先使用取模运算获取各个位的数字//个位int theUnit=number/10000;//十位int decade=number/1000%10;//百位int hundreds=number/100%10;//千位int kilobit=number%100/10;//万位int myriabit=number%100%10;int invert=myriabit*10000+kilobit*1000+hundreds*100+decade*10+theUnit;System.out.println("反转之后的五位整数是"+invert);}
}

使用基本数据类型的包装类、字符串数组以及算术运算根据距离和时间计算速度

package net.ittimeline.java.core.operator.arithmetic;/*** @author liuguanglei 18601767221@163.com* @create 2019-07-30 15:44* @website www.ittimeline.net* @since JDK11.03*/
public class Velocity {public static void main(String[] args) {//实例化数组args=new String[]{"1200","300"};//数组中需要两个元素if(args.length<2){System.err.println("需要俩参数");//系统异常退出System.exit(1);}//使用包装类将字符串转换为floatfloat distance=Float.parseFloat(args[0]);//args[0]表示访问数组的第一个元素//args[1]表示访问数组的第二个元素float time=Float.parseFloat(args[1]);//float和float运算的类型是floatSystem.out.print("Velocity = ");System.out.print(distance/time);}
}

3.3 自增(自减)运算符

自增运算符主要用于变量自增1,用于变量自增1的运算符是++,但是++可以放在变量前面,也可以放在变量后面,放在前面时,变量先自增1,然后再参与运算,++放在变量的后面,变量先运算,再自增1。

自减运算符使用--表示,用于变量自减1,也可以放在变量的前面和后面,分别表示先减1,再参与运算和先参与运算,再减1。

  • 自增(自减)运算符不会改变变量本身的数据类型,因此在运算时需要考虑当前数据类型的极限值
  • 自增(自减)运算符如果是一条单独的语句,前置++(--)和后置++(--)的效果是一样的

自增运算符案例

package net.ittimeline.java.core.operator.autoincrement;/*** 前置++,后置++* 作用是针对整型变量加1* 自增运算不会改变变量本身的数据类型* @author liuguanglei 18601767221@163.com* @create 2019-07-28 10:32* @website www.ittimeline.net* @since JDK11.03*/
public class AutoincrementAddTest {public static void main(String[] args) {//自增运算符是单独的语句,前置++和后置++的结果是一样的int tmp=10;tmp++;System.out.println("tmp = "+tmp);int val=10;++val;System.out.println("val = "+val);int num=10;//后置++,先运算,后自增1int result=num++;//result=10System.out.println("result = "+result);//num=11System.out.println("num ="+num);int source=10;//前置++ 先自增1,后运算result=++source;//result=11System.out.println("result ="+result);//source=11System.out.println("source ="+source);short shortVal=10;//shortVal的类型还是shortSystem.out.println(shortVal++);byte byteVal=10;//byteVal的数据类型还是byteSystem.out.println(byteVal++);}
}

自减运算符应用案例

package net.ittimeline.java.core.operator.autoincrement;/*** 自减运算符* @author liuguanglei 18601767221@163.com* @create 2019-07-28 10:42* @website www.ittimeline.net* @since JDK11.03*/
public class AutoincrementSubTest {/*** 自减运算符* @param args*/public static void main(String[] args) {int num=10;//先运算,后减1int result=num--;System.out.println("result = "+result);System.out.println("numb = "+num);int source=10;//先减1再运算int target= --source;System.out.println("target = "+target);System.out.println("source = "+source);}
}

自增(自减)运算符的常用应用场景就是在for循环中改变循环条件的值。

package net.ittimeline.java.core.operator.autoincrement;/*** 自增和自减运算符的应用场景** @author liuguanglei 18601767221@163.com* @create 2019-08-03 09:23* @website www.ittimeline.net* @since JDK11.03*/
public class AutoincrementApp {public static void main(String[] args) {System.out.println("自增运算符的应用场景");//自增运算符的应用场景//定义一个字符串String content="Java架构师成长之道";//将字符串转换为字符数组char[] contents=content.toCharArray();//循环遍历字符数组 这里的c++表示将循环的初始条件自增1for (char c =0;c<content.length();c++){System.out.print(contents[c]+" ");}//自减运算的应用场景System.out.println("自减运算的应用场景");String car="法拉利拉法";char[] carDesc=car.toCharArray();for(int i=carDesc.length-1;i>=0;i--){System.out.print(carDesc[i]+"");}}
}

自增自减运算符复杂案例

package net.ittimeline.java.core.operator.autoincrement;/*** 自增运算符复杂案例** @author liuguanglei 18601767221@163.com* @create 2019-08-03 09:40* @website www.ittimeline.net* @since JDK11.03*/
public class AutoIncrementComplexTest {public static void main(String[] args) {int i = 10;int j = 20;// i++ 等价于i+=1 等价于i=int k = i++;//k=10System.out.println("k = " + k);//i =11System.out.println("i = " + i);k = ++i;//k = 12System.out.println("k = " + k);//i =12System.out.println("i = " + i);k = j--;//k=20System.out.println("k =" + k);//j=19System.out.println("j = " + j);k=--j;//k=18System.out.println("k = " + k);//j=18System.out.println("j = " + j);}}

自增运算符的本质:让变量自增的三种方式

package net.ittimeline.java.core.operator.autoincrement;/*** 自增运算的本质** @author liuguanglei 18601767221@163.com* @create 2019-08-03 10:33* @website www.ittimeline.net* @since JDK11.03*/
public class AutoincrementEssence {public static void main(String[] args) {int number = 12;number++;System.out.println("number = " + number);//等价于number = 12;number += 1;System.out.println("number = " + number);//等价于number=12;number=number+1;System.out.println("number = " + number);}
}

3.4 赋值运算符

赋值通常是给变量赋值,Java中使用"="来表示赋值,而"=="表示相等,赋值是将=右边的值或者表达式赋值给左边的变量。

  • 当赋值号(=)两边的数据类型不一致时,可以使用自动类型转换或者强制类型转换进行处理
  • 支持连续赋值,即同时声明并赋值多个变量
  • 赋值运算不会改变变量本身的数据类型
package net.ittimeline.java.core.operator.assignment;/*** 赋值运算符* =* 算术运算和赋值运算* += -= *= /= %=** 赋值运算不会改变变量的数据类型** @author liuguanglei 18601767221@163.com* @create 2019-07-28 10:59* @website www.ittimeline.net* @since JDK11.03*/
public class AssignmentTest {public static void main(String[] args) {//声明变量并赋值int i=10;int j=10;//连续赋值,同时声明两个变量k,l并赋值为10int k=10,l=10;System.out.println("i = "+i+ " j = "+j +" k = "+k+ " l = "+l);//赋值的左边必须是变量,右边可以是变量值,也可以是表达式//计算四个整数的和int result=i+j+k+l;System.out.println("result = "+result);int o,p,q;//同时赋值o=p=q=20;System.out.println("o = "+o+ " p = "+p +" q = "+q);//赋值不会改变变量的数据类型//通常情况下byte和int运算的类型是intbyte byteVal=12;byteVal=(byte)(byteVal+1);System.out.println("byteVal = "+byteVal);//但是如果使用赋值运算,不会改变变量的数据类型byteVal=12;byteVal+=1;System.out.println("byteVal = "+byteVal);}
}

JDK提供了java.util.Random类用于生成随机数,详细的使用说明可以查阅JDK API文档,后续在编写应用案例时,可以使用它来生成测试数据。

package net.ittimeline.java.core.operator.assignment;import java.util.Random;/***产生0-99之间的随机数* @author liuguanglei 18601767221@163.com* @create 2019-07-28 10:59* @website www.ittimeline.net* @since JDK11.03*/
public class RandomTest {public static void main(String[] args) {/***  创建一个随机数*  88表示初始种子,种子相同,每次产生的序列相同,种子不同,每次产生的序列不同*  */Random random=new Random(88);//生成0-99之间的整数int left=random.nextInt(100);int right=random.nextInt(100);System.out.println("left = "+left+" right ="+right);}}

赋值运算符还可以可算术运算符结合使用,例如+= ,-=,*=,/=,%=。

package net.ittimeline.java.core.operator.assignment;
import static java.lang.System.out;import java.util.Random;/*** 算术运算与赋值运算结合运算** @author liuguanglei 18601767221@163.com* @create 2019-07-29 14:02* @website www.ittimeline.net* @since JDK11.03*/
public class MathOps {public static void main(String[] args) {//创建一个随机数对象Random random=new Random(88);int i,j,k;//随机产生一个1-100之间的整数j=random.nextInt(100)+1;k=random.nextInt(100)+1;out.println("j = "+j);out.println("k = "+k);i=j+k;out.println("j + k = "+i);i=j-k;out.println("j - k = "+i);i=j*k;out.println("j * k = "+i);i=j/k;out.println("j / k = "+i);i=j%k;out.println("j % k = "+i);j%=k;out.println("j %= k "+j);float u,v,w;v=random.nextFloat();w=random.nextFloat();out.println("v = "+v);out.println("w = "+w);u=v+w;out.println("v + w = "+u);u=v-w;out.println("v - w = "+u);u=v*w;out.println("v * w = "+u);u=v/w;out.println("v / w = "+u);u+=v;out.println("u+v = "+u);u-=v;out.println("u-v = "+u);u*=v;out.println("u*v = "+u);u/=v;out.println("u/v = "+u);}
}

复杂的赋值运算符

package net.ittimeline.java.core.operator.assignment;/*** 赋值运算符的复杂案例* 开发中尽量将表达式写的简单明了,有利于程序的维护* @author liuguanglei 18601767221@163.com* @create 2019-08-03 11:24* @website www.ittimeline.net* @since JDK11.03*/
public class AssignmentComplex {public static void main(String[] args) {int m=2;int n=3;/*** 拆解表达式* n*=m++* n=n*m++* n=3*2* n=6* m=3*/n*=m++;System.out.println("n = "+n);System.out.println("m = "+m);n=4;/*** 拆解表达式*         n+=(n++)+(++n);*         n=n+(n++)+(++n)*         n=4+4+6*         n=14*/n+=(n++)+(++n);System.out.println("n = "+n);}
}

3.5 JDK1.5新特性-静态导入

  • 静态导入是使用import static关键字加上类名[.变量名][.方法名],其中[.变量名]和[.方法名]是可选的,如果没有,默认就是导入类的所有变量和方法到当前类中,这样就可以直接在当前类中使用。
package net.ittimeline.java.core.jdk.feature.jdk5;
/*** import static关键字是直接导入某个类的所有变量和方法到本类中* 这样就可以直接在当前类中引用导入导入类的变量和方法** import static java.lang.System.*表示导入System的所有变量和方法*/import  static java.lang.System.*;/*** JDK5新特性之静态导入* @author liuguanglei 18601767221@163.com* @create 2019-08-03 11:38* @website www.ittimeline.net* @since JDK11.03*/
public class StaticImport {public static void main(String[] args) {//因为静态导入过System类,这样可以在当前类中调用System的成员变量out和err的println方法out.println("Hello World");err.println("Hello World Again");}
}

使用静态导入和SimpleDateFormat实现输出当前日期

package net.ittimeline.java.core.operator;
import java.text.SimpleDateFormat;
import java.util.Date;import static java.lang.System.out;
/*** 静态导入** @author liuguanglei 18601767221@163.com* @create 2019-07-29 13:48* @website www.ittimeline.net* @since JDK11.03*/
public class HelloDate {/***     声明日期格式*/public static final String PATTERN="yyyy-MM-dd HH:mm:ss";public static void main(String[] args) {//创建日期格式化对象SimpleDateFormat simpleDateFormat=new SimpleDateFormat(PATTERN);String now =simpleDateFormat.format(new Date());//显示输出当前日期out.print(now);}
}

3.6 关系运算符

关系运算符用于判断数据的关系,Java中常用的关系运算符有大于(>),小于(<),等于(==),不等于(!=),大于等于(>=),小于等于(<-=)。

  • 关系运算符的运算结果是boolean类型,也就是true或者false
  • 相等性用==表示,而不是=
  • >=表示大于或者等于,>=表示小于或则等于
  • >,>=,<,<=只能用在基本数据类型的数值类型之间进行比较
  • ==可以使用在基本数据类型和引用类型之间相等性判断

===的差别

package net.ittimeline.java.core.operator.relation;/*** ==和=的差别* @author liuguanglei 18601767221@163.com* @create 2019-08-03 11:36* @website www.ittimeline.net* @since JDK11.03*/
public class Equals {public static void main(String[] args) {int i=10;int j=20;//== 判断相等性,运算结果是falseSystem.out.println("i == j = "+(i==j));//=表示将右边的值或者表达式赋值给左边的变量System.out.println("i = j  = "+(i=j));}
}

在使用关系运算符之前先对之前的输出语句System.out.println()结合JDK5.0新特性之静态导入
做一个更加"简短"的输出。

然后借助JDK的Random类生成两个1-100以内的随机整数,用关系运算符运算,并输出运算结果

package net.ittimeline.java.core.operator.relation;import java.util.Random;import static java.lang.System.out;/*** 关系运算符** @author liuguanglei 18601767221@163.com* @create 2019-07-29 13:19* @website www.ittimeline.net* @since JDK11.03*/
public class Bool {public static void main(String[] args) {Random random = new Random(88);//产生两个1-100之内的随机整数int i = random.nextInt(100)+1;int j = random.nextInt(100)+1;//输出 i和 j的值out.println("i = " + i);out.println("j = " + j);//使用关系运算符比较i和j的值out.println("i > j is " + (i > j));out.println("i < j is " + (i < j));out.println("i >= j is " + (i >= j));out.println("i <= j is " + (i <= j));out.println("i == j is " + (i == j));out.println("i != j is " + (i != j));}}

3.7 ==和equals()的区别

  • ==和equals都是比较的值是否相等,通常基本数据类型使用判断,引用数据类型使用equals判断,而如果使用判断引用数据类型,比较的是对象的引用地址。

Java中所有的类(无论是JDK自带的还是开发人员自己定义的)的直接或者间接父类都是java.lang.Object,该类有个成员方法equals,用于比较对象的相等性。

从Object的equals方法看的出来,默认比较的是对象的引用地址

 public boolean equals(Object obj) {return (this == obj);}

那么问题来了

EqualsMethod2类中,明明Value的成员变量i的值是100,理论上来说应该是相等的。
但是使用equals判断的时候是不相等,因为只要使用关键字new创建对象时,会开辟新的堆内存空间存储对象。

package net.ittimeline.java.core.operator.relation;/*** 相等性判断** @author liuguanglei 18601767221@163.com* @create 2019-07-29 13:40* @website www.ittimeline.net* @since JDK11.03*/
public class EqualsMethod2 {public static void main(String[] args) {Value v1=new Value();Value v2=new Value();v1.i=v2.i=100;//没有重写equals时,默认比较的是对象的地址//这里创建了两个Value对象,因此equals()判断为falseSystem.out.println("v1.equals(v2) = "+(v1.equals(v2)));}}class Value{int i;}

因为Object类的equals方法比较的是对象的地址是否相等,但是在实际开发中,经常比较的是对象的成员变量是否相等,因此绝大多数类都重写了equals方法。

这里以Integer类为例子,分别使用==和equals来判断Integer对象的相等性。

当创建Integer对象的值在-128-127之间时,无论是equals还是==都是相等的。
因为Integer类中有个内部类IntegerCache,用于缓存Integer的值在-128-127之间的对象

private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}

而如果Integer的值超过了缓存的范围,那么使用判断对象相等时就不会相等了。
在开发过程中尽量使用equals方法来判断,而不是使用来判断。

package net.ittimeline.java.core.operator.relation;/*** 相等性判断** @author liuguanglei 18601767221@163.com* @create 2019-07-29 13:34* @website www.ittimeline.net* @since JDK11.03*/
public class EqualsMethod {public static void main(String[] args) {//因为Integer类缓存-128-127之间的实例Integer n1= Integer.valueOf(Byte.MAX_VALUE);Integer n2= Integer.valueOf(Byte.MAX_VALUE);//因此无论是equals还是==都是相等System.out.println("n1.equals(n2) = "+(n1.equals(n2)));System.out.println("n1==n2 = "+(n1==n2));//但是超过了缓存的范围Integer n3=Integer.valueOf(300);Integer n4=Integer.valueOf(300);System.out.println("n3.equals(n4) = "+(n3.equals(n4)));//==就为false了,因为对象的地址不同System.out.println("n3==n4 = "+(n3==n4));}
}

3.8 逻辑运算符

逻辑运算符用于布尔类型变量或者布尔表达式的逻辑运算,Java支持的逻辑运算符有如下几种:

  • 逻辑与(&):&两边同时为true,结果为true
  • 短路与(&&):当&&两边为true,结果为true,如果&&的一边为false,将不再执行剩余的表达式,也就是短路特性。
  • 逻辑或(|):当|两边只要有一个为true,结果为true,否则结果为false
  • 短路或(||):当||两边只要有一个为true,结果为true,否则结果为false,并且不再执行剩余表达式,也就是短路特性。
  • 逻辑非(!):当一个变量或者表达式的结果为true,!的结果为false,否则结果为true,逻辑非就是相反的结果
  • 逻辑亦或():当两边结果同时为true或者false,结果为false,否则为true。

一般开发中使用短路与、短路或,不会使用逻辑与和逻辑或。

package net.ittimeline.java.core.operator.logic;import java.util.Random;/*** 逻辑运算* @author liuguanglei 18601767221@163.com* @create 2019-08-03 13:02* @website www.ittimeline.net* @since JDK11.03*/
public class LogicTest {public static void main(String[] args) {Random random=new Random(88);//创建两个随1-100之内的随机数int left=random.nextInt(100)+1;int right=random.nextInt(100+1);System.out.println("left ="+left);System.out.println("right ="+right);//判断两个数都是大于100boolean result=left>100&&right>100;System.out.println("left>100&&right>100 = "+result);//判断左边的数加上100大于100或者右边的数大于100result=left+100>100||right>100;System.out.println("left+100>100||right>100 = "+result);//逻辑非result=!result;System.out.println("!result = "+result);//逻辑亦或//^左右两边都为true或者false,结果为falseresult =left>10^right>10;System.out.println("left>10^right>10 = "+result);result=left>50^right>50;//^左右两边结果不同结果为trueSystem.out.println("left>50^right>50 = "+result);}
}

逻辑与和短路与的区别

package net.ittimeline.java.core.operator.logic;/*** 逻辑与与短路与* 逻辑与&左右两边都是true,结果为true,不具备短路特性* 短路与&&左右两边都是true,结果为true,具备短路特性:明确整体的计算结果,不在计算剩余的表达式* @author liuguanglei 18601767221@163.com* @create 2019-08-03 13:02* @website www.ittimeline.net* @since JDK11.03*/
public class LogicAndShowCircuitTest {public static void main(String[] args) {boolean flag=false;int num=10;//逻辑与不具备短路特性,虽然&左边已经是falseboolean logicAnd=flag&num++>0;//但是从输出结果看出num依然自增1System.out.println("num = "+num);//而 短路与&&具备短路特性num=10;// &&左边已经为false,右边的num没有自增1boolean logicAndCircuit=flag&&num++>0;//输出结果依然为10System.out.println("num = "+num);}
}

逻辑与的短路特性

package net.ittimeline.java.core.operator.logic;import static java.lang.System.out;
/*** 逻辑运算的短路现象** @author liuguanglei 18601767221@163.com* @create 2019-07-29 19:41* @website www.ittimeline.net* @since JDK11.03*/
public class ShowCircuit {static boolean test1(int val){out.println("test1("+val+")");out.println("result: "+(val<1));return val<1;}static boolean test2(int val){out.println("test1("+val+")");out.println("result: "+(val<2));return val<2;}static boolean test3(int val){out.println("test1("+val+")");out.println("result: "+(val<3));return val<3;}public static void main(String[] args) {/*** 逻辑与的短路特性* 当执行到test1方法时,2<2的结果为false,整体表达式的结果为false,因此不会再执行test3方法*/boolean flag=test1(0)&&test1(2)&&test3(2);out.println("expression is "+flag);}
}

逻辑或的短路特性

package net.ittimeline.java.core.operator.logic;import static java.lang.System.out;
/*** 逻辑运算的短路现象** @author liuguanglei 18601767221@163.com* @create 2019-07-29 19:41* @website www.ittimeline.net* @since JDK11.03*/
public class LogicOrCircuit {static boolean test1(int val){out.println("test1("+val+")");out.println("result: "+(val<1));return val<1;}static boolean test2(int val){out.println("test1("+val+")");out.println("result: "+(val<2));return val<2;}static boolean test3(int val){out.println("test1("+val+")");out.println("result: "+(val<3));return val<3;}public static void main(String[] args) {/*** 逻辑或的短路特性* 当执行到test1方法时,0<2的结果为true,整体表达式的结果为false,因此不会再执行tes2和test3方法*/boolean flag=test1(0)||test2(2)||test3(2);out.println("expression is "+flag);}
}

逻辑与、短路与和逻辑或、短路或的应用案例

package net.ittimeline.java.core.operator.logic;/*** 逻辑运算符的复杂案例* 结合自增运算、if(true){}* @author liuguanglei 18601767221@163.com* @create 2019-08-03 15:55* @website www.ittimeline.net* @since JDK11.03*/
public class LogicComplex {public static void main(String[] args) {int x = 1;int y = 1;//x++=1  y++=1 if (x++ == 2 & y++ == 2) {x = 7;}//x=2 y=2System.out.println("x = " + x + " y = " + y);x = 1;y = 1;// ++x=2 ++y =2 if trueif (++x == 2 && ++y == 2) {x = 7;}//x=7 y=2System.out.println("x = " + x + " y = " + y);x = 1;y = 1;//x++ =1 ++y=2 if trueif (x++ == 1 | ++y == 1) {x = 7;}//x=7 y=2System.out.println("x = " + x + " y = " + y);x = 1;y = 1;// x++=1 // x=7 y=1if (x++ == 1 || ++y == 1) {x = 7;}//x=7 y=1System.out.println("x = " + x + " y = " + y);}}

3.9 三元运算符

三元运算符用于布尔变量或者布尔表达式判断,需要三个操作数,等价于if/else,其表现形式为
bool-exp?value0:value1,如果布尔表达式的结果为true,三目运算的结果为value0,否则为value1。

使用三目运算符模拟扔硬币

package net.ittimeline.java.core.operator.ternary;import java.util.Random;/*** 使用三元运算符模拟扔硬币* @author liuguanglei 18601767221@163.com* @create 2019-07-30 16:07* @website www.ittimeline.net* @since JDK11.03*/
public class CoinFlipping {public static void main(String[] args) {Random random=new Random(88);boolean flip=random.nextBoolean();System.out.print("OUTCOME :");System.out.println(flip?"人头":"字");}
}

三目运算符和if/else

package net.ittimeline.java.core.operator.ternary;
import static java.lang.System.out;
/*** 三目运算符和if/else** @author liuguanglei 18601767221@163.com* @create 2019-07-30 10:21* @website www.ittimeline.net* @since JDK11.03*/
public class TernaryIfElese {/*** 三目运算符* @param i* @return*/static int ternary(int i){return i<10?i*100:i*10;}/*** 标准的if/else* @param i* @return*/static int standardIfElse(int i){if(i<10){return i*100;}else{return i*10;}}public static void main(String[] args) {out.println(ternary(9));out.println(ternary(11));out.println(standardIfElse(9));out.println(standardIfElse(11));}
}

使用嵌套if和三目运算符求三个整数的最大值

package net.ittimeline.java.core.operator.ternary;/*** 求三个数中的最大值* 分别使用if/else if和三元运算符* @author liuguanglei 18601767221@163.com* @create 2019-08-04 16:58* @website www.ittimeline.net* @since JDK11.03*/
public class GetMaxNumber {public static void main(String[] args) {int i=277;int j=20;int k=-99;int max=0;if(i>j){if(i>k){max=i;}else{max=k;}}System.out.println("使用if/else if实现求三个整数的最大值 max = "+max);max= i>j&&i>k?i:k;System.out.println("三个数中的最大值是"+max);}
}

使用三元运算符判断用户输入的整数是基数还是偶数
如果想要用户输入数据,需要使用Java提供的Scanner类实现

package net.ittimeline.java.core.operator.ternary;import java.util.Scanner;/*** 判断用户输入的数字是基数还是偶数** @author liuguanglei 18601767221@163.com* @create 2019-08-04 17:32* @website www.ittimeline.net* @since JDK11.03*/
public class ParityCheck {public static void main(String[] args) {//创建一个虚拟键盘Scanner input = new Scanner(System.in);System.out.println("请输入一个整数");int number = input.nextInt();String result = number % 2 == 0 ? "这是一个偶数" : "这个是一个奇数";System.out.println("你输入的数字是" + number);System.out.println(result);}
}

3.10 位运算符

位运算符是直接对整数的二进制进行运算,在JDK的原码中大量使用了位运算,
以下是截取Integer类的numberofLeadingZeros方法

    @HotSpotIntrinsicCandidatepublic static int numberOfLeadingZeros(int i) {// HD, Count leading 0'sif (i <= 0)return i == 0 ? 32 : 0;int n = 31;if (i >= 1 << 16) { n -= 16; i >>>= 16; }if (i >= 1 <<  8) { n -=  8; i >>>=  8; }if (i >= 1 <<  4) { n -=  4; i >>>=  4; }if (i >= 1 <<  2) { n -=  2; i >>>=  2; }return n - (i >>> 1);}

位运算符操作的都是整数类型,因为是基于二进制运算,其运行效率高。
在日常开发中几乎不会使用到位运算,但是后期会阅读大量JDK源码,了解底层实现机制,因此必须掌握位运算符的基本使用。

Java中支持的位运算符有如下几种:

  • 左移(<<): 左移N位相当于乘以2的n次方,空位补0,被移除的高位丢弃,空缺位补0

  • 右移(>>):右移N位相当于除以2的n次方,被移位的二进制最高位是0,右移后,空缺位补0,最高位是1,最高位补1

  • 无符号右移(>>>):不管最高位的符号位,右移N位相当于除以2的N次方,被移位的二进制最高位无论是0还是1,空缺位都补0

  • 按位与(&):只有&两边都是1,结果是1,否则就是0

  • 按位或(|):只要|两边都是0,结果是0,否则就是1

  • 按位亦或(^):相同的二进制位进行亦或运算,结果是0,不相同的二进制位运算结果是1

  • 取反运算(~):无论正负数取反运算,各二进制位按照补码取反

  • &,|,在操作布尔类型的时候表示为逻辑与、逻辑或、逻辑亦或,&、|、在操作整数的时候表示为按位与与按位或、按位亦或。

左移运算

package net.ittimeline.java.core.operator.bit;/*** 左移运算** @author liuguanglei 18601767221@163.com* @create 2019-08-03 16:26* @website www.ittimeline.net* @since JDK11.03*/
public class BitLeftMoveTest {public static void main(String[] args) {//8的二进制表示为// 0000 0000 0000 0000 0000 0000 0000 1000int number=8;//因为8是正数,左移动2位,右边补上0,相当于乘以2的两次方 也就是乘以4// 0000 0000 0000 0000 0000 0000 0010 0000number=number<<2;System.out.println("8<<2 ="+number);/*** 在进行移位运算时需要考虑数据越界的问题*/int value=21;// 0000 0000 0000 0000 0000 0000 0101 0100//左边移动26位//101 0100 0000 0000 0000 0000 0000 0000 0//最高位1 表示结果为负数System.out.println("21<<26 = "+(value<<26));}
}

使用左移计算2*16的结果

package net.ittimeline.java.core.operator.bit;/*** 使用左移计算2*16** @author liuguanglei 18601767221@163.com* @create 2019-08-04 17:36* @website www.ittimeline.net* @since JDK11.03*/
public class BitLeftMoveArithmetic {public static void main(String[] args) {int number=2;//2 * 16 用左移就是2左移4位int result=number<<4;System.out.println("2*16="+result);}
}

右移运算

package net.ittimeline.java.core.operator.bit;/*** 右移运算** @author liuguanglei 18601767221@163.com* @create 2019-08-03 16:45* @website www.ittimeline.net* @since JDK11.03*/
public class BitRightMoveTest {public static void main(String[] args) {//0000 0000 0000 0000 0000 0000 0001 0000int number=16;//右移N位,相当于除以2的N次方 16/4 结果是4//00 0000 0000 0000 0000 0000 0000 0001 00number=number>>2;System.out.println("16 >> 2 = "+(number));number=-16;// -16/4 结果是-4number=number>>2;System.out.println("-16 >> 2 ="+(number));}
}

按位与、按位或、按位亦或、按位非运算

package net.ittimeline.java.core.operator.bit;/*** 按位运算符* & 两边都是1,结果为1* |* ^* @author liuguanglei 18601767221@163.com* @create 2019-08-03 17:22* @website www.ittimeline.net* @since JDK11.03*/
public class BitAndOrXor {public static void main(String[] args) {/*** 5的二进制表示方式为 0000 0000 0000 0000 0000 0000 0000 0101* 9的二进制方式表示为 0000 0000 0000 0000 0000 0000 0000 1001** 0101&1001  =0001 因此 5&9的结果是1* 0101|1001 = 1101 因此 5|9的结果是13* 0101^1001 = 1100 因此 5^9的结果是12* 9 ->0000 0000 0000 0000 0000 0000 0000 1001* ~9  1111 1111 1111 1111 1111 1111 1111 0110 原码*     1000 0000 0000 0000 0000 0000 0000 1001 反码*     1000 0000 0000 0000 0000 0000 0000 1010 补码* ~9    最终的结果是-10***/System.out.println("5&9 = "+(5&9));System.out.println("5|9 = "+(5|9));System.out.println("5^9 = "+(5^9));System.out.println("~9 = "+(~9));System.out.println(Integer.toBinaryString(-10));}
}

有符号左移

package net.ittimeline.java.core.operator.bit;import static java.lang.System.out;/*** 有符号右移** @author liuguanglei 18601767221@163.com* @create 2019-07-30 16:23* @website www.ittimeline.net* @since JDK11.03*/
public class SignedRightShift {public static void main(String[] args) {int i = 0x80000000;out.println(Integer.toBinaryString(i));//等价于i=i>>1i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));i >>= 1;out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));}
}

无符号右移

package net.ittimeline.java.core.operator.bit;import static java.lang.System.out;/*** 无符号右移** @author liuguanglei 18601767221@163.com* @create 2019-07-30 16:33* @website www.ittimeline.net* @since JDK11.03*/
public class UnsignedRightShift {public static void main(String[] args) {int i = -1 << 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;out.println(Integer.toBinaryString(i));i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;i >>>= 1;out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));out.println(Integer.toBinaryString(i));}
}

使用亦或运算实现变量的交换

package net.ittimeline.java.core.operator.bit;/** 使用亦或因运算实现变量交换* @author liuguanglei 18601767221@163.com* @create 2019-08-04 17:11* @website www.ittimeline.net* @since JDK11.03*/
public class BitXorVariableSwap {public static void main(String[] args) {int left=10;int right=20;System.out.println("变量交换之前 left = "+left+" right = "+right);left=left^right;right=left^right;left=left^right;System.out.println("变量交换之后 left = "+left+" right = "+right);}
}

转载于:https://www.cnblogs.com/ittimeline/p/11295963.html

Java架构师成长之道之Java数据计算相关推荐

  1. Java架构师成长之道之Java架构师技术栈

    Java架构师成长之道之Java架构师技术栈 Java架构师成长之道 JavaSE篇 Java概述与开发环境搭建 Java数据存储 Java数据运算 Java程序流程控制 Java数组 Java面向对 ...

  2. Java架构师成长之道之Java程序流程控制

    Java架构师成长之道之Java程序流程控制 Java架构师成长之道 4.1 程序流程控制概述 之前编写的绝大多数程序都是顺序执行,也就是从main函数开始,由上到下一行一行的执行,也被称为顺序结构. ...

  3. Java架构师成长之道之浅谈计算机系统架构

    Java架构师成长之道之浅谈计算机系统架构 Java架构师成长之旅 1.1 信息技术发展趋势 目前信息技术主要经历了互联网.移动互联网以及以大数据.云计算.人工智能和区块链为代表的新兴技术三个阶段.而 ...

  4. Java架构师成长之道之计算机组成原理组成篇

    Java架构师成长之道之计算机组成原理组成篇 Java架构师成长之道 2.1 计算机总线 2.1.1 总线概述 以通用串行总线USB(Universial Serial Bus)为例子来理解什么是总线 ...

  5. Java架构师成长之路

    目录导航 前言 一.源码分析专题 1.1 设计模式详解 1.2 Mybatis源码分析 1.3 Spring5源码分析 二.分布式架构专题 2.1 漫谈分布式架构 2.2 分布式架构的基础 2.3 分 ...

  6. Java架构师成长直通车(一):学习指南

    大型网站的特点和设计宗旨 罗马不是一天建成的,对应的,大型网站也不是一来就有的.淘宝诞生在马云的家中,谷歌一开始是在斯坦福大学的宿舍中设计出来的,后面搬到了车库中.任何大型网站不可能一来就设计成能扛得 ...

  7. 阿里 P9 整理出:Java 架构师“成长笔记”共计 23 版块

    阿里巴巴一位 P9 级架构师总结出的共计 23 版块的 Java 架构师"成长笔记",一经发布就受到了众多 Java 程序员同学的追捧,这份"成长笔记"涵盖了: ...

  8. java架构师_成为一名Java高级架构师究竟要学哪些东西??

    Java架构师,应该算是一些Java程序员们的一个职业目标了吧.很多码农码了五六年的代码也没能成为架构师.那成为Java架构师要掌握哪些技术呢,总体来说呢,有两方面,一个是基础技术,另一个就是组织能力 ...

  9. 一线Java架构师概括互联网公司的标准Java技术架构

    一线Java架构师概括互联网公司的标准Java技术架构 大部分人对于BAT的技术有一种莫名的崇拜感,觉得只有非常牛逼和天才才能做出现在的这些系统,但经过前面两篇博文的分析,我们可以看到其实并没有什么神 ...

最新文章

  1. SpirngMVC jsp页面空指针
  2. MetaPhlAn2-增强版宏基因组分类谱工具-一条命令获得宏基因组物种组成
  3. POJ 2356 (抽屉原理)
  4. 重学TCP协议(7) Timestamps 选项
  5. java向上转型不能调用子类独有的方法
  6. Cookie介绍与操作
  7. cuda nvidia安装程序失败_Ubuntu16.04安装nvidia-docker
  8. 团队成员的分应该怎么分?
  9. 加强网站安全、重构公司的门户网站项目(C# VS2003)
  10. 计算机网络遴选的试题,税收信息化基础知识试题含答案
  11. php家族族谱代码,家族族谱系统设计.doc
  12. 简单易懂的现代魔法-递归
  13. window10无法自动修复此计算机,Win10系统自动修复无法修复电脑如何解决
  14. 视频、图形图像处理之Opencv技术记录(四)、OpenCV教程概述
  15. 为什么需要使用云计算技术?
  16. 利用audacity分析浊音、清音、爆破音的时域及频域特性
  17. Linux CentOS集群搭建(三台)(一)
  18. 热插拔与非热插拔的区别
  19. 阿里云1+X-云计算开发与运维-中级(多选题)
  20. ESP8266实现WIFI局域网连接手机APP监控

热门文章

  1. DNS and Bind (二)
  2. ios 开发框架原始雏形 01
  3. Oracle X$Tables
  4. [JavaScript] FireBug 调试
  5. 微软对外开放更多软件技底层代码术文档
  6. Java 对象的序列化和反序列化
  7. android工作注意事项
  8. android资源的热更新(替换 AssetManager+LoadedApk中的资源路径)
  9. Android 水波纹点击效果(Ripple Effect)
  10. Managing the Lifecycle of a Bound Service