您的位置:首页 > 编程语言 > Java开发

Java易混淆点总结01_equals和 == 有什么区别?_选择排序和冒泡排序有什么区别?_取余和取模有什么区别?

2019-05-11 21:20 253 查看

易混淆点总结

1.equals和 == 有什么区别?

==如果是基本数据类型,则比较的是值,如果是引用类型,则比较的是地址

equals是比较字符是否都相同

[code]//	运行结果:
//	2018699554
//	2018699554
//	1311053135
//	字符串a与字符串b的地址相等
//	字符串a与字符串c的地址 不 相等
//	字符串a与字符串c存的字符相同
public static void main(String[] args) {
// System.identityHashCode(a)返回对象a的内存地址的哈希值
String a="abc";
String b="abc";
String c = new String("abc");
//分别打印 a b c 的地址的哈希值
System.out.println(System.identityHashCode(a));
System.out.println(System.identityHashCode(b));
System.out.println(System.identityHashCode(c));
if(a==b) {	//==是比较地址是否相等
System.out.println("字符串a与字符串b的地址相等");
}else {
System.out.println("字符串a与字符串b的地址 不 相等");
}
if(a==c) {
System.out.println("字符串a与字符串c的地址相等");
}else {
System.out.println("字符串a与字符串c的地址 不 相等");
}
if(a.equals(c)) {
System.out.println("字符串a与字符串c存的字符相同");
}else {
System.out.println("字符串a与字符串c存的字符 不 相同");
}
}

为什么a与b的地址相同?

因为新建变量b的时候虚拟机会在堆内存中查找是否已存在abc这字符串,如果已经存在这字符串则b的地址就等于a的地址

 为什么a与c的地址不同?

因为新建字符串变量c的时候用了new,它会在堆内存中申请一个新的空间来存储变量c的值,申请了新的内存自然c的内存地址就与a的地址不一样了

 2.为什么像下图这样数组超出长度也不会报错?

 

因为new的时候会在内存中新开辟一段空间来存储name这数组,它的地址和所占内存空间都改变了 

3.Java数组定义和赋值与C语言有什么区别?

Java不允许定义数组长度的同时对数组进行赋值,而C语言可以

[code]		int [] a=new int [3] {1,2,3};	//错误 不可以声明数组长度的同时对数组进行初始化
int [] b=new int [3];	//正确
int [] c={1,2,3};	//正确 声明变量的时候直接对数组初始化是可以简写的
int [] d=new int [] {1,2,3};	//正确 不简写也是可以的
int [] e;	//正确
e={1,2,3};	//错误 声明数组后才赋值不可以简写
e=new int[] {1,2,3};	//正确
int f[]={1,2,3};	//正确但不推介

 Java的数组长度定下来以后是不能再改变的,因为数组是开辟一段连续的内存空间进行存储的,如果长度在确定了以后还能增加的话就不能保证在内存中下一个位置是空余的,如果为了增加数组长度强行替换了内存中的数据那么电脑程序有可能会出现各种错误

4.增强for循环的语法及缺点是什么?

[code]		String [] a= {"a","b","c"};
for(String i:a) {	//数组为其他类型时不要把i的类型错写成int
System.out.print(i+" ");

优点:简洁

缺点:无法逆序访问    不能访问数组的特定部分只能遍历整个数组    不能改变数组中元素的值

 问:下面图中红圈部分是不是改变了字符串数组a的值?

 答:没有改变字符串数组a的值,只是改变了 i 的值

5.选择排序和冒泡排序有什么区别?

选择排序:

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。
性质:不稳定的排序方法

简单选择排序的比较次数与序列的初始排序无关。 假设待排序的序列有 n 个元素,选择排序的赋值操作介于 0 和 3 (n - 1) 次之间; 则比较次数 永远都是n (n- 1) / 2; 而移动次数(即:交换操作)与序列的初始排序有关,介于 0 和 (n - 1) 次之间。当序列正序时,移动次数最少,为 0。当序列反序时,移动次数最多,为n - 1 次;逆序交换n/2次。综上,简单选择排序的时间复杂度为 O(n²)
选择排序的移动次数比冒泡排序少多了,由于交换所需CPU时间比 比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快

[code]		//选择排序
int [] a= {4,2,3,6,5};
for(int i=0;i<a.length-1;i++) {			//length-1=5 i最大值为5 length=6
int min_index = i;
for(int j=i+1;j<a.length;j++) {		//最多运行6-1=5次 注意内层的for循环不用-1因为它是从i+1开始
if(a[min_index]>a[j]) {
min_index=j;
}
}
int temp=a[min_index];
a[min_index]=a[i];
a[i]=temp;
}
for(int i:a) {
System.out.print(i+" ");
}

冒泡排序:

通俗的意思就是讲,在一组数据中,相邻元素依次比较大小,最大的放后面,最小的冒上来

注:该图是较小的冒到前面,不过思想和最大的冒到后面是一样的

[code]		//冒泡排序 小-大 左-右
int [] a= {4,2,3,6,5};
for(int i=0;i<a.length-1;i++) {
for(int j=0;j<a.length-1-i;j++) {
if(a[j]>a[j+1]) {
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i:a) {
System.out.print(i+" ");
}

问:选择排序和冒泡排序的不同在哪里?

选择排序是执行完内循环后进行数组元素的交换,冒泡排序是每发现后一个元素比前一个元素小就交换元素位置

选择排序的内循环次数是:(数组的长度-已排好元素个数-1)for(int j=i+1;j<a.length;j++)

冒泡排序的内循环次数是:(数组长度-1-已排好元素个数)   for(int j=0;j<a.length-1-i;j++)

虽然选择排序和冒泡排序的内循环次数都是相同的,但他们开始和结束的地方是不一样的,选择排序内循环是从已排好元素的个数的后一个元素开始的,一直循环到最后一个元素才结束,而冒泡排序的内循环是每次都是从第一个元素开始到已排好元素的前一位结束。

从下表看上去冒泡排序似乎比选择排序的时间复杂度差不多,但一般来说冒泡排序要比选择排序慢得多

选择排序是不稳定的(相同的值在排序后有可能前后位置变换),而冒泡排序是稳定的(相同的值在排序后不会变换位置)

排序方法 平均时间 最好时间 最坏时间
选择排序(不稳定) O(n^2) O(n^2) O(n^2)
冒泡排序(稳定) O(n^2) O(n) O(n^2)

 4.原码 反码 补码 是什么?

正数的 原码 反码 补码 都相同

负数的原码:其正数的原码符号位变为1

           反码:除符号位以外其他全部取反(0变为1,1变为0)

           补码 :反码+1(是二进制的+1)

例:5的原码:0101 反码:0101 补码:0101

      -5的原码:1101 反码:1010 补码:1011

(-3)+(-5)的运算过程:

-3 原码:1000 1011 反码:1111 1100 补码:1111 1101

-5 原码:1000 1101 反码:1111 1010 补码:1111 1011

  1111 1101

+1111 1011

=1 1111 1000(补码)

补码求原码过程:补码除符号位以外取反 后 +1

补码除符号位以外取反:1000 0111

1000 0111 + 0000 00001 = 1000 1000(-8)

5.取余和取模有什么区别?

对于整数a,b来说,取模运算或者求余运算的方法要分如下两步:

1.求整数商:c=a/b

2.计算模或者余数:r=a-(c*b)

求模运算和求余运算在第一步不同

取余运算在计算商值向0方向舍弃小数位

取模运算在计算商值向负无穷方向舍弃小数位

例如:4/(-3)约等于-1.3

在取余运算时候商值向0方向舍弃小数位为-1

在取模运算时商值向负无穷方向舍弃小数位为-2

所以

4rem(-3)=1
4mod(-3)=-2

在Java中取余符号是 % 取余是向0取整,可以理解为舍去小数

而取模是向下取整

10与-3取余:

10-(-3)*(-3)=1

取余的结果正负只与被余数(10)的正负相同

10与-3取模:

10-(-3)*(-4)=-2

6.前置++与后置++有什么区别?

无论是前置++还是后置++,都会对变量本身进行+1

前置 ++exp 会对变量本身进行+1,表达式的结果是变量+1之后的结果

后置 exp++:会对变量本身进行+1,表达式的结果是变量+1之前的结

7.按位与 按位或 异或 按位取反 是什么?

 & 按位与,左侧的操作数和右侧的操作数全部都转换成补码形式, 然后对位操作
规则:两个同时为1的时候,则返回1,否则返回0

| 按位或

规则:两个同时为0的时候,则返回0,否则返回1

           如果有任何一个返回1,则为1,否则返回0

 ^ 异或

规则:判断两个数是否相同,如果相同,则返回0,否则返回1

 ~ 按位取反(一元运算符)

所有的位,包括符号位都取反

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: