赞
踩
java中int最大值,2的31次方-1,为什么不是2的32次方-1?
——因为第一位是符号位,0表示正数,1表示复数;
-1的二进制:
11111111111111111111111111111111
Integer.Min的二进制:
10000000000000000000000000000000
为什么?
规则:符号位是1,表示负数,剩下的位数全部要取反。
在Java中,int是一个32位的整数,其中一个二进制位是符号位(0代表正数,1代表负数)。如果你对一个负数取反,实际上是对其负值加1。这是因为取反操作是对整数的二进制表示进行按位取反操作,不考虑符号位。当你对一个负数取反时,符号位也会被取反,导致得到一个非常大的正数,这个数等于该负数的绝对值减1。例如,对于负数-5(二进制表示为1111 1111 1111 1111 1111 1111 1111 1011),取反操作会得到一个正数(二进制表示为0000 0000 0000 0000 0000 0000 0000 0101),这个数等于-5的绝对值(5)减1(4)。如果你需要对一个负数进行按位取反,然后再恢复原来的值,你可以先对数字取绝对值,然后对结果加1,进行按位取反操作,最后如果需要的话再转换回原来的符号。
示例代码:
int number = -5; // 假设是一个负数
int absoluteValue = number < 0 ? -number + 1 : number;
int inverted = ~absoluteValue;
// 现在inverted是按位取反后的结果
// 如果需要转换回原来的负数
int originalNegative = -inverted;
拓展阅读:
负数取反java 负数取反符号位变吗
+、-、#、/、%,等运算,在计算机系统中,都不是十进制的,所有的这些算术符号,在底层都是用二进制的位运算实现的。
位运算有哪些?
为什么这么设计?
原因:为了让计算机在运算的时候,走一套逻辑,而不用走正数一套逻辑,负数一套逻辑;都是 取反+1;
底层的东西,效率非常重要,越底层应该越高效;
——一开始我猜的是0;
实际跑出来是多少,看下图:
结论:还是它自己,用取反+1,可以算出来,它还是自己。
另:0取反之后还是它自己!
0: 0000 …… 0000
取反 1111 …… 1111
+1: 每一位都要进一,最后溢出了,溢出了就不要了,所以:
0000 …… 0000
public static void print(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
public static void main(String[] args) { // 32位 // int num = -1; // // print(num); // // // int test = 1123123; // print(test); // print(test<<1); // print(test<<2); // print(test<<8); // // // int a = Integer.MAX_VALUE; // System.out.println(a); print(-1); int a = Integer.MIN_VALUE; print(a); // int b = 123823138; // int c = ~b; // print(b); // print(c); // print(-5); // System.out.println(Integer.MIN_VALUE); // System.out.println(Integer.MAX_VALUE); // int a = 12319283; // int b = 3819283; // print(a); // print(b); // System.out.println("============="); // print(a | b); // print(a & b); // print(a ^ b); // int a = Integer.MIN_VALUE; // print(a); // print(a >> 1); // print(a >>> 1); // // int c = Integer.MIN_VALUE; // int d = -c ; // // print(c); // print(d); }
public class Code02_SumOfFactorial { public static long f1(int N) { long ans = 0; for (int i = 1; i <= N; i++) { ans += factorial(i); } return ans; } public static long factorial(int N) { long ans = 1; for (int i = 1; i <= N; i++) { ans *= i; } return ans; } public static long f2(int N) { long ans = 0; long cur = 1; for (int i = 1; i <= N; i++) { cur = cur * i; ans += cur; } return ans; } public static void main(String[] args) { int N = 10; System.out.println(f1(N)); System.out.println(f2(N)); } }
冒泡排序(Bubble Sort)是一种简单的排序算法,它的基本思想是通过不断交换相邻两个元素的位置,使得较大的元素逐渐往后移动,直到最后一个元素为止。冒泡排序的时间复杂度为 O ( n 2 ) O(n^2)O(n 2 ),空间复杂度为 O ( 1 ) O(1)O(1),是一种稳定的排序算法。
其实现过程可以概括为以下几个步骤:
public class Code05_BubbleSort { public static void bubbleSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int end = arr.length - 1; end > 0; end--) { for (int i = 0; i < end; i++) { if (arr[i] > arr[i + 1]) { swap(arr, i, i + 1); } } } } // 交换arr的i和j位置上的值 public static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
冒泡排序虽然时间复杂度较高,但是它的实现简单,容易理解,并且在某些特定场景下仍然有着广泛的应用。以下是一些冒泡排序的应用场景:
需要注意的是,如果待排序的数据量较大,或者数据分布比较随机,冒泡排序的效率会比较低,不如其他排序算法。因此,在实际应用中,需要根据具体的情况选择适合的排序算法。
在 Spring 框架中,冒泡排序算法并没有直接应用到核心模块中,但是它可以作为一种排序算法被使用在 Spring 的某些模块中,例如:
需要注意的是,冒泡排序算法虽然简单,但是在实际应用中效率较低,因此在处理大规模数据时不建议使用。在 Spring 框架中,如果需要进行排序操作,建议使用更高效的排序算法,例如快速排序、归并排序等。
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。(引用于百度百科)
选择排序的具体实现过程如下:
选择排序的时间复杂度为 O(n^2),其中 n 是待排序序列的长度。虽然选择排序的时间复杂度较高,但是它的实现简单,容易理解,并且在某些特定场景下仍然有着广泛的应用。需要注意的是,选择排序是一种不稳定的排序算法,即相等的元素在排序前后的相对位置可能会发生改变。
public class Code04_SelectionSort { public static void selectionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 0; i < arr.length - 1; i++) { int minIndex = i; for (int j = i + 1; j < arr.length; j++) { if(arr[j] < arr[minIndex]) { minIndex = j; } } swap(arr, i, minIndex); } } public static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } // for test public static void comparator(int[] arr) { Arrays.sort(arr); } // for test public static int[] generateRandomArray(int maxSize, int maxValue) { // Math.random() [0,1) // Math.random() * N [0,N) // (int)(Math.random() * N) [0, N-1] int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; for (int i = 0; i < arr.length; i++) { // [-? , +?] arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); } return arr; } // for test public static int[] copyArray(int[] arr) { if (arr == null) { return null; } int[] res = new int[arr.length]; for (int i = 0; i < arr.length; i++) { res[i] = arr[i]; } return res; } // for test public static boolean isEqual(int[] arr1, int[] arr2) { if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { return false; } if (arr1 == null && arr2 == null) { return true; } if (arr1.length != arr2.length) { return false; } for (int i = 0; i < arr1.length; i++) { if (arr1[i] != arr2[i]) { return false; } } return true; } // for test public static void printArray(int[] arr) { if (arr == null) { return; } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } // for test public static void main(String[] args) { int testTime = 500000; int maxSize = 100; int maxValue = 100; boolean succeed = true; for (int i = 0; i < testTime; i++) { int[] arr1 = generateRandomArray(maxSize, maxValue); int[] arr2 = copyArray(arr1); selectionSort(arr1); comparator(arr2); if (!isEqual(arr1, arr2)) { succeed = false; printArray(arr1); printArray(arr2); break; } } System.out.println(succeed ? "Nice!" : "Fucking fucked!"); int[] arr = generateRandomArray(maxSize, maxValue); printArray(arr); selectionSort(arr); printArray(arr); }
选择排序虽然时间复杂度较高,但是它的实现简单,容易理解,并且在某些特定场景下仍然有着广泛的应用。以下是一些适合使用选择排序的场景:
需要注意的是,选择排序的时间复杂度较高,因此在处理大规模数据时,应该使用其他更高效的排序算法。
在 Spring 中,选择排序并不是一个常用的算法,因此它并没有被直接应用在 Spring 框架中。然而,选择排序的思想可以启发我们在 Spring 中的一些实践,例如:
虽然选择排序并不是 Spring 中的常用算法,但是它的思想可以启发我们在 Spring 中的一些实践,从而提高代码的可读性和可维护性。
插入排序(Insertion Sort)是一种简单直观的排序算法,它的基本思想是将待排序序列分为已排序区间和未排序区间,然后每次从未排序区间取出一个元素,将其插入到已排序区间的合适位置中,使得插入后仍然保持已排序区间有序。重复这个过程,直到未排序区间为空,整个序列有序为止。
具体来说,插入排序的实现可以分为两个步骤:
public static void insertionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 1; i < arr.length; i++) { // 0 ~ i 做到有序 for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { swap(arr, j, j + 1); } } } // i和j,数交换 public static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
插入排序适用于以下场景:
插入排序适用于数据规模较小、数据基本有序、辅助排序算法和链表排序等场景,但对于大规模数据排序,效率较低,因此在实际应用中需要根据具体情况选择合适的排序算法。
在 Spring 框架中,插入排序主要用于 BeanFactory 的初始化工作中,即对 BeanDefinitionMap 中的 BeanDefinition 进行排序。
在 Spring 中,BeanDefinitionMap 是一个 Map 类型的数据结构,其中包含了所有的 BeanDefinition。当 Spring 容器启动时,需要对 BeanDefinition 进行排序,以便在后续的 Bean 实例化过程中能够正确地解析依赖关系。
为了实现 BeanDefinition 的排序,Spring 使用了插入排序算法。具体来说,Spring 使用了一个名为 SimpleAliasRegistry 的类来管理 BeanDefinition,其中包含了一个名为 singletonObjects 的 Map,用于存储已经实例化的单例 Bean。在初始化 BeanFactory 时,Spring 会对 BeanDefinition 进行排序,并按照排序后的顺序依次实例化 Bean,并将其存储到 singletonObjects 中。
以下是 Spring 中插入排序的示例代码:
public class SimpleAliasRegistry implements AliasRegistry { private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16); private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); private final Set<String> registeredSingletons = new LinkedHashSet<>(256); private final List<String> singletonCurrentlyInCreation = new ArrayList<>(16); private volatile boolean singletonsCurrentlyInDestruction = false; private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); // ... public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) { this.beanDefinitionMap.put(beanName, beanDefinition); this.frozenBeanDefinitionNames = null; } public void preInstantiateSingletons() throws BeansException { List<String> beanNames = new ArrayList<>(this.beanDefinitionMap.keySet()); // 对 BeanDefinition 进行排序 Collections.sort(beanNames, new Comparator<String>() { @Override public int compare(String beanName1, String beanName2) { return getPriority(beanName1) - getPriority(beanName2); } }); // 依次实例化 Bean for (String beanName : beanNames) { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd.isSingleton()) { if (bd.isLazyInit()) { this.registerLazyInit(beanName, bd); } else { this.getBean(beanName); } } } } // ... }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。