> Java > java지도 시간 > 본문

Java에서 int를 문자열로 변환하는 것과 문자열을 int로 변환하는 효율성의 차이점은 무엇입니까?

王林
풀어 주다: 2023-05-12 08:46:16
앞으로
1057명이 탐색했습니다.

    int를 string으로 변환하는 것과 string을 int로

    string을 int로 변환하는 효율성 비교, 두 가지 방법

    Interger.parseInt(String)
    Interger.valueOf(String).intValue()
    로그인 후 복사

    두 번째 방법은 소스코드에서 볼 수 있고, 첫 번째 방법을 구현해 놓은 것입니다.

    Java에서 int를 문자열로 변환하는 것과 문자열을 int로 변환하는 효율성의 차이점은 무엇입니까?

    댓글은 아마도 다음을 의미할 것입니다

    /**
          *返回一个包含整数的对象
          *指定的{@ String String}的值。 这个说法是
          *被解释为表示一个有符号的十进制整数
          *就好像这个论据是给予{@link的
          * #parseInt(java.lang.String)}方法。 结果是一个
          表示整数值的整数对象
          *由字符串指定。
         *
          换句话说,这个方法返回一个{@code Integer}
          *对象等于以下值:
         *
          * <blockquote>
          * {@code new Integer(Integer.parseInt(s))}
          * </ blockquote>
         *
          * @param是要解析的字符串。
          * @返回一个保存值的{整数}对象
          *由字符串参数表示。
          * @exception NumberFormatException如果字符串不能被解析
          *作为一个整数。
         */
    로그인 후 복사

    parseInt() 메소드는 valueOf()에서 구현됩니다. 두 번째 시간은 첫 번째 시간보다 훨씬 빠릅니다.

     Integer.parseInt(str) : 21
     Integer.valueOf(str).intValue() : 14
    로그인 후 복사

    int 문자열을 변환하는 방법에는 일반적으로 세 가지가 있습니다

    • 첫 번째 방법: number + ""

    • 두 번째 방법: string.valueOf()

    • 세 번째 방법: .toString()

    • 먼저 단순하고 투박한 첫 번째 유형에 대해 이야기해 보겠습니다.

    • 두 번째 방법: 맨 아래 레이어는 여전히 .toString() 메서드를 사용합니다

    • 세 번째 방법은 toString()

    코드입니다.

    int num = 888888;
     
            //(1)num + ""
            long start = System.currentTimeMillis();//得到开始运行时系统时间
            for(int i=0; i<100000; i++){
                String str = num + "";
            }
            long end = System.currentTimeMillis();//得到结束运行时系统时间
            System.out.println("num + \"\" : " + (end - start));
     
            //(2)String.valueOf(num)
            start = System.currentTimeMillis();
            for(int i=0; i<100000; i++){
                String str = String.valueOf(num);
            }
            end = System.currentTimeMillis();
            System.out.println("String.valueOf(num) : " + (end - start));
     
            //(3)Integer.toString(num)
            start = System.currentTimeMillis();
            for(int i=0; i<100000; i++){
                String str = Integer.toString(num);
            }
            end = System.currentTimeMillis();
            System.out.println("Integer.toString(num) : " + (end - start));
    로그인 후 복사

    결과는

    num + "" : 82
    String.valueOf(num) : 32
    Integer.toString(num) : 9

    많은 반복 테스트 끝에 toString()이 가장 빠릅니다. num+" "가 가장 느리고, String.valueOf()를 사용했을 때 소스코드는 이렇습니다.

    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
    로그인 후 복사

    즉, 사용할 때 전달된 객체가 null인지 판단할 필요는 없지만 전달된 객체가 비어 있으면 null 값 대신 null 문자열이 반환된다는 점에 특히 주의하세요. . 필수입니다. 기억하세요.

    문자열을 int로 변환하는 문제

    많은 학생들이 인터뷰 중에 String 유형을 int 유형으로 변환하는 함수를 캡슐화해 달라고 요청하면서 이러한 문제에 직면한 적이 있을 것입니다. 겉으로는 간단해 보이는 이 문제는 실제로 많은 세부 사항을 숨기고 있으며, 이 기능을 실제로 캡슐화하는 것은 쉽지 않습니다. 면접관이 조사하고 싶은 것은 실제로 알고리즘 자체의 난이도가 아닙니다. 면접관이 주로 조사하고 싶은 것은 프로그래머가 얼마나 신중하게 코드를 작성하고 문제가 포괄적인지 고려하는 것입니다. 즉, 우리는 코드를 견고하게 만들기 위해 최선을 다해야 합니다. 아래에서는 이 문제에 숨겨진 세부 사항을 단계별로 분석합니다.

    Analytic

    우선, 함수 호출자가 전달한 데이터가 정확하다고 가정하면, 다음 코드를 작성하는 것은 쉽습니다.

        public int strToInt(String str) {
            int number = 0;
            for (int i=0; i<str.length(); i++) {
                number *= 10;
                number += (str.charAt(i) - &#39;0&#39;);
            }
            return number;
        }
    로그인 후 복사

    위 코드는 string 각 문자는 해당 정수로 변환된 후 정수 데이터 번호에 하나씩 통합됩니다.

    이러한 코드를 면접관에게 제출하면 결과는 절대 만족스럽지 못할 것입니다. 우리가 캡슐화하는 기능은 API 인터페이스와 동일하며 모든 개발자에게 제공됩니다. 다른 개발자가 이상한 매개변수를 전달하지 않는 것은 불가피하며 이 코드는 비정상적인 매개변수에 응답하지 않습니다. . 처리가 완료되면 예외 매개변수가 전달되면 프로그램이 직접 충돌합니다. 다음으로, 우리는 이 기능을 단계적으로 개선하고 견고성을 향상시킬 것입니다.

    1. 들어오는 문자열이 빈 문자열이거나
        public int strToInt(String str) throws NumberFormatException{
            if (str == null || str.contentEquals("")) { // 如果传入的字符串为空对象或者传入的字符串为空字符串,则抛出异常
                throw new NumberFormatException("null or empty string"); // 这里直接利用java封装好的异常类,当然我们也可以自己封装异常类,面试官要考察的不是对异常类的封装,而是你要知道要处理异常情况
            }
            int number = 0;
            for (int i=0; i<str.length(); i++) {
                number *= 10;
                number += (str.charAt(i) - &#39;0&#39;);
            }
            return number;
        }
    로그인 후 복사

    먼저 문자열이 비어 있는지 또는 빈 문자열인지 확인합니다. 그렇다면 여기서는 직접 예외가 발생합니다. Java로 캡슐화된 예외 클래스 NumberFormatException이 사용됩니다. 물론 우리는 예외 클래스를 직접 캡슐화할 수도 있습니다. 면접관이 조사하려는 것은 예외 클래스의 캡슐화가 아니라 예외를 처리하는 방법을 알아야 한다는 것입니다.

    2. 부호 비트 처리에 관해

    들어오는 숫자가 음수일 가능성이 있는지 미리 면접관에게 물어보는 것이 좋습니다. 그렇다면 부호 비트가 허용됩니까? , 우리는 그것을 처리해야 합니다. 부호 비트가 처리됩니다. 음수의 첫 번째 문자가 "-"인지 여부만 판단하면 들어오는 숫자가 음수인지 알 수 있습니다. 양수에 부호 비트가 허용되면 A 문자는 "+"일 수 있으므로 이에 따라 처리해야 합니다.

        public int strToInt(String str) throws NumberFormatException{
            if (str == null || str.contentEquals("")) { // 如果传入的字符串为空对象或者传入的字符串为空字符串,则抛出异常
                throw new NumberFormatException("null or empty string"); // 这里直接利用java封装好的异常类,当然我们也可以自己封装异常类,面试官要考察的不是对异常类的封装,而是你要知道要处理异常情况
            }
            boolean negative = false; // negative为true表示是负数,反之为正数
            int pos = 0;
            if (str.charAt(0) == &#39;-&#39;) { // 如果为负数
                negative = true;
                pos++; // 调过第一位符号位
            } else if (str.charAt(0) == &#39;+&#39;) {
                pos++; // 调过第一位符号位
            }
            int number = 0;
            while (pos < str.length()) {
                number *= 10;
                number += (str.charAt(pos) - &#39;0&#39;);
                pos++;
            } 
            return negative ? -number : number; // 如果为负数则返回对应的负数
        }
    로그인 후 복사
    3. 잘못된 문자 처리

    함수 호출자가 전달할 수 있습니다. "abc23123"과 같은 지저분한 문자열도 그에 따라 처리해야 합니다. 호출자에게 수신 문자열이 잘못된 문자열임을 알리기 위해 예외를 발생시켜야 합니다.

        public int strToInt(String str) throws NumberFormatException{
            if (str == null || str.contentEquals("")) { // 如果传入的字符串为空对象或者传入的字符串为空字符串,则抛出异常
                throw new NumberFormatException("null or empty string"); // 这里直接利用java封装好的异常类,当然我们也可以自己封装异常类,面试官要考察的不是对异常类的封装,而是你要知道要处理异常情况
            }
            boolean negative = false; // negative为true表示是负数,反之为正数
            int pos = 0;
            if (str.charAt(0) == &#39;-&#39;) { // 如果为负数
                negative = true;
                pos++; // 调过第一位符号位
            } else if (str.charAt(0) == &#39;+&#39;) {
                pos++; // 调过第一位符号位
            }
            int number = 0;
            while (pos < str.length()) {
                if (str.charAt(pos) >= &#39;0&#39; && str.charAt(pos) <= &#39;9&#39;) { // 只有字符在&#39;0&#39;到&#39;9&#39;的范围内,才算正确的字符
                    number *= 10;
                    number += (str.charAt(pos) - &#39;0&#39;);
                    pos++; 
                } else {
                    throw new NumberFormatException("invalid string"); // 当字符是其他字符时,抛出异常告知调用者传入的字符串错误
                }
            } 
            return negative ? -number : number; // 如果为负数则返回对应的负数
        }
    로그인 후 복사
    4. 범위를 벗어난 정수 데이터

    호출자가 전달한 문자열은 매우 긴 문자열일 수 있으며, 정수로 변환하면 "12345678674324334"와 같이 정수의 저장 범위를 초과할 수 있습니다. 수신 문자열이 저장 범위를 초과했음을 호출자에게 알리는 예외:

        public int strToInt(String str) throws NumberFormatException{
            if (str == null || str.contentEquals("")) { // 如果传入的字符串为空对象或者传入的字符串为空字符串,则抛出异常
                throw new NumberFormatException("null or empty string"); // 这里直接利用java封装好的异常类,当然我们也可以自己封装异常类,面试官要考察的不是对异常类的封装,而是你要知道要处理异常情况
            }
            boolean negative = false; // negative为true表示是负数,反之为正数
            int pos = 0;
            if (str.charAt(0) == &#39;-&#39;) { // 如果为负数
                negative = true;
                pos++; // 调过第一位符号位
            } else if (str.charAt(0) == &#39;+&#39;) {
                pos++; // 调过第一位符号位
            }
            int limit = negative ? (-Integer.MIN_VALUE) : Integer.MAX_VALUE;
            int mult = limit / 10; // 记录最大数/10,让number和这个数比较,如果大于它,则number * 10肯定也就大于最大数
            int number = 0;
            while (pos < str.length()) {
                if (str.charAt(pos) >= &#39;0&#39; && str.charAt(pos) <= &#39;9&#39;) { // 只有字符在&#39;0&#39;到&#39;9&#39;的范围内,才算正确的字符
                    if (number > mult) {// 让number和mult比较,如果大于它,则number * 10肯定也就大于最大数
                        throw new NumberFormatException("input string beyond int size");
                    }
                    number *= 10;
                    int digit = str.charAt(pos) - &#39;0&#39;;
                    if (number > limit - digit) { // 这里不能用number + digit > limit来判断,因为number + digit可能超出整数的存储范围,相加后的数可能是一个负数,但是limit - digit肯定不会超出
                        throw new NumberFormatException("input string beyond int size");
                    } else {
                        number += digit;
                    }
                    pos++;
                } else {
                    throw new NumberFormatException("invalid string"); // 当字符是其他字符时,抛出异常告知调用者传入的字符串错误
                }
            } 
            return negative ? -number : number; // 如果为负数则返回对应的负数
        }
    로그인 후 복사

    위 코드에서 숫자가 최대 정수를 초과할지 여부를 판단할 때 먼저 해당 값(최대 정수/10)을 비교합니다. 10을 곱하여 최대 정수와 비교하는 방법입니다. 숫자 * 10이 정수 범위를 초과하면 데이터 오버플로가 발생하여 얻은 값이 음수가 될 수 있기 때문입니다. 10) 데이터 오버플로가 발생하지 않습니다. 이 또한 작은 세부 사항입니다. 어쩌면 이 기능이 완벽하다고 생각하실 수도 있겠지만, 이제 위의 글은 틀렸다는 점을 말씀드리고 싶습니다.

    为什么呢?这要从整数的范围说起,整数的取值范围是(-2^31)至(2^31 - 1),从绝对值的角度看,最小负数相比于最大正数大1。所以上面代码中(-Integer.MIN_VALUE)会超出整形的范围,造成数据溢出,也就是说上面的代码对负数最小范围的限制的处理是错误的。那么怎么解决这个问题呢?

    我们换个角度思考,最小负数的绝对值比最大正数的绝对值大1,那(-Integer.MAX_VALUE)的值肯定不会超出整数的范围,我们现在的程序是以正数的方式处理,如果反过来已负数的方式处理,问题不就解决了吗?修改代码如下:

        public int strToInt(String str) throws NumberFormatException{
            if (str == null || str.contentEquals("")) { // 如果传入的字符串为空对象或者传入的字符串为空字符串,则抛出异常
                throw new NumberFormatException("null or empty string"); // 这里直接利用java封装好的异常类,当然我们也可以自己封装异常类,面试官要考察的不是对异常类的封装,而是你要知道要处理异常情况
            }
            boolean negative = false; // negative为true表示是负数,反之为正数
            int pos = 0;
            if (str.charAt(0) == &#39;-&#39;) { // 如果为负数
                negative = true;
                pos++; // 调过第一位符号位
            } else if (str.charAt(0) == &#39;+&#39;) {
                pos++; // 调过第一位符号位
            }
            int limit = negative ? Integer.MIN_VALUE : (-Integer.MAX_VALUE);
            int mult = limit / 10;
            int number = 0;
            while (pos < str.length()) {
                if (str.charAt(pos) >= &#39;0&#39; && str.charAt(pos) <= &#39;9&#39;) { // 只有字符在&#39;0&#39;到&#39;9&#39;的范围内,才算正确的字符
                    if (number < mult) {
                        throw new NumberFormatException("input string beyond int size");
                    }
                    number *= 10;
                    int digit = str.charAt(pos) - &#39;0&#39;;
                    if (number < limit + digit) {
                        throw new NumberFormatException("input string beyond int size");
                    } else {
                        number -= digit;
                    }
                    pos++;
                } else {
                    throw new NumberFormatException("invalid string"); // 当字符是其他字符时,抛出异常告知调用者传入的字符串错误
                }
            } 
            return negative ? number : -number;
        }
    로그인 후 복사

    OK,现在我们把能够想到的异常情况处理了。再来考虑一个问题,为什么整形数据的范围是(-2^31)至(2^31 - 1),最小负数的绝对值比最大正数的绝对值要大1呢?

    5、int数据范围的讨论

    我们知道,一个int类型占四个字节,也就是32位,其中第一位是符号位,符号位为0表示正数,为1表示负数,其余31位表示数值。正常来说int类型的数据范围应该是(-2^31-1)到(2^31-1),为什么负数会多一位呢?

    我们首先看一下Java代码中对Integer.MAX_VALUE和Integer.MIN_VALUE的定义:

        /**
         * A constant holding the minimum value an {@code int} can
         * have, -2<sup>31</sup>.
         */
        public static final int   MIN_VALUE = 0x80000000;
     
        /**
         * A constant holding the maximum value an {@code int} can
         * have, 2<sup>31</sup>-1.
         */
        public static final int   MAX_VALUE = 0x7fffffff;
    로그인 후 복사
    原码、反码、补码

    我们知道,在计算机中,数据都是以二进制的形式存储的,比如,数字10,其二进制形式就是1010。

    一个字节有8位,每位可以存储一个01字符,byte类型占1个字节,也就是8位,其中,最高位是符号位,用来表示数值是正数还是负数,符号位为0表示正数,符号位为1表示负数。我们先来看一下原码、反码、补码的定义:

    • 原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。

    • 反码:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

    • 补码:补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)

    正数的原码、反码、补码都是其本身;负数的反码是在其原码的基础上,符号位不变,其余个位取反,负数的补码是其反码的基础上+1。

    举例说明(下面都以byte类型进行举例):

    数据原码反码补码
    10000010100000101000001010
    -10100010101111010111110110

    计算机中,数据都是以补码的形式存储的。为什么要以补码的形式存储呢?有两个原因:

    1、如果数值以补码的形式保存,对一个数进行求补运算,可以得到其相反值

    求补运算:将一个数(包括正数和负数)所有二进制位(包括符号位和数值位)取反,然后在最低位加上1。

    为什么对一个数进行求补运算,可以得到其相反值呢?我们先来分析一下求补运算的定义,现将所有的二进制取反,然后+1,首先一个数和它所有位取反得到的数相加,其结果肯定是11111111,这是因为它们每一位都不一样,然后将结果+1,即11111111 + 1,结果是1 00000000,最高位的1已经溢出,换种方式说,如果以f(n)表示对n进行求补运算,那么对于任意的范围内的数,可以得到:

    n + f(n) = 1 00000000
    로그인 후 복사

    f(n) = 1 00000000 - n
    로그인 후 복사
    로그인 후 복사

    而对于一个正数来说,对其进行求补运算其实得到的就是它的相反数的补码(负数的补码符号位保持不变,其他为全部取反再+1,因为正数和负数的符号位本来就不一样,所以对一个正数进行求补其实得到的就是它的相反数的补码)。

    那么对于一个负数来说呢?对其进行求补运算是否能够得到其对应的正数的补码呢?

    假设n>0,根据上面可知:

    f(n) = 1 00000000 - n
    로그인 후 복사
    로그인 후 복사

    对f(n)进行求补运算,有:

    f(f(n)) = f(1 00000000 - n) = 1 00000000 - (1 00000000 - n) = n
    로그인 후 복사

    其中,1 00000000 - n表示n对应负数的补码,对其进行求补运算得到的就是n,正数的补码就是其原码。

    由上可知:如果数值以补码的形式保存,对一个数进行求补运算,可以得到其相反值,即:f(n) = -n

    2、方便减法运算

    如果数值以补码的方式存储,可以将减法变为加法,省去了减法器,通过上面的推导,如果数据以补码的方式存储,以f(n)表示对n进行求补运算,可以得到:

    f(n) = -n
    로그인 후 복사

    那么现在我们需要计算m - n,应该要怎么计算呢?如果以补码的方式存储,那么就有:

    m - n = m + (-n) = m + f(n)
    로그인 후 복사

    也就是说,减去一个数只需要加上对其进行求补运算后得到的值即可。

    3、使用补码存储数据,可以对任意的两个数直接进行相加运算,不用考虑符号位

    4、通过补码形式存储,规定10000000对应的负数的最小值,也就是-128。

    由上面可知,如果是byte类型,数据范围应该为[-128,127],最小负数要比最大正数多一位。

    위 내용은 Java에서 int를 문자열로 변환하는 것과 문자열을 int로 변환하는 효율성의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    관련 라벨:
    원천:yisu.com
    본 웹사이트의 성명
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
    인기 튜토리얼
    더>
    최신 다운로드
    더>
    웹 효과
    웹사이트 소스 코드
    웹사이트 자료
    프론트엔드 템플릿