Java基础之基本数据类型封装类的缓存

1、Java中基本数据类型byte、short、char、int、long、float、double、boolean有对应的封装类型:Byte、Short、Character、Integer、long、Float、Double,Boolean其中Byte、Short、Character、Integer、Long、Boolean都实现了常量池缓存。Byte、Short、Character、Integer、Long通过静态内部Cache类来实现一定范围(下面列出缓存范围)内的数据缓存,而Boolean通过两个静态常量TRUE、FALSE来实现数据缓存。

  • Byte类缓存范围:[-128,127] 共256个值。
  • Short类缓存范围:[-128,127] 共256个值。
  • Character类缓存范围:[0,127] 共128个值。
  • Integer类默认缓存范围:[-128,127] 共256个值,可以通过修改VM参数-XX:AutoBoxCacheMax=200 即可修改缓存上限到200
  • Long类缓存范围:[-128,127] 共256个值。
  • Boolean类就缓存两个值:true、false。
2、装箱和拆箱过程:
装箱:调用封装类 valueOf(x) 方法;
拆箱:调用封装类的 xxValue() 方法。

3、测试
测试前说明:
==对于基本数据类型和对象的比较含义是不同的。对于基本数据类型:“==” 比较的是基本数据类型的数值;对于对象:“==” 比较的是对象在内存中的内存地址。
byte、short、char类型计算后会自动转成整型类型int。

(1)Byte


    static void testByte(){
        System.out.println("Byte类型:");
        Byte i1 = 127;
        Byte i2 = 127;
        Byte i3 = 0;
        Byte i4 = new Byte("127");
        Byte i5 = new Byte("127");
        Byte i6 = new Byte("0");

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为数值在[-128,127]的范围内,使用常量池缓存中的127

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池Byte对象127,i4指向堆中Byte对象127

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型byte做加法运算,
        //计算结果是整型的127,所以最终是基本数据类型的值作比较;(byte、short、char类型计算后会自动转成整型类型int)
        System.out.println("127=i5+i6 " + (127 == i5 + i6)); //true
        System.out.println("byte计算后,转换类型为:"+ myGetType(i5 + i6));  // int

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型byte做加法运算,计算结果是整型的127;
        // i1与基本数据类型127比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型byte做加法运算,计算结果是整型的127;
        // i4与基本数据类型127比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true

        /* Byte类中有缓存静态内部类ByteCache;缓存范围:-128~127,共256(cache.length)个值
        private static class ByteCache {
            private ByteCache(){}

            static final Byte cache[] = new Byte[-(-128) + 127 + 1];

            static {
                for(int i = 0; i < cache.length; i++)
                    cache[i] = new Byte((byte)(i - 128));
            }
        }
         */
    }

(2)Short


    static void testShort(){
        System.out.println("Short类型:");
        Short i1 = 127;
        Short i2 = 127;
        Short i3 = 0;
        Short i4 = new Short("127");
        Short i5 = new Short("127");
        Short i6 = new Short("0");
        Short i1New = 128;
        Short i2New = 128;

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为数值在[-128,127]的范围内,使用常量池缓存中的127

        System.out.println("i1New=i2New " + (i1New == i2New));  //false 超过缓存范围,创建新对象了

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池对象127,i4指向堆中对象127

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型short做加法运算,
        //计算结果是整型的127,所以最终是基本数据类型的值作比较;(byte、short、char类型计算后会自动转成整型类型int)
        System.out.println("127=i5+i6 " + (127 == i5 + i6)); //true
        System.out.println("short计算后,转换类型为:"+ myGetType(i5 + i6));  // int

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型short做加法运算,计算结果是整型的127;
        // i1与基本数据类型127比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型short做加法运算,计算结果是整型的127;
        // i4与基本数据类型127比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true

        /* Short类中有缓存静态内部类ShortCache;缓存范围:-128~127,共256(cache.length)个值
        private static class ShortCache {
            private ShortCache(){}

            static final Short cache[] = new Short[-(-128) + 127 + 1];

            static {
                for(int i = 0; i < cache.length; i++)
                    cache[i] = new Short((short)(i - 128));
            }
        }
         */
    }

(3)Character


    static void testChar(){
        System.out.println("Character类型:");
        Character i1New72 = 72;
        Character i1 = 40; //表示字符'('
        Character i2 = 40;
        Character i3 = 32;
        Character i4 = new Character('(');//字符'('的十进制码点值是40
        Character i4New72 = new Character('H');//字符'H'的十进制码点值是72
        Character i5 = new Character('(');
        Character i6 = new Character(' '); //空格的十进制码点值是32
        Character i1New = 128;
        Character i2New = 128;
        Character i1New1 = 127;
        Character i2New2 = 127;

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为数值在[0,127]的范围内,使用常量池缓存中的40

        System.out.println("i1New=i2New " + (i1New == i2New));  //false 超过缓存范围,创建新对象了

        System.out.println("i1New1=i2New2 " + (i1New1 == i2New2));  //true 没有超过缓存范围,使用常量池缓存中的值

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池Character对象40,i4指向堆中Character对象40

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型char做加法运算,
        //计算结果是整型的72,所以最终是基本数据类型的值作比较;(byte、short、char类型计算后会自动转成整型类型int)
        System.out.println("72=i5+i6 " + (72 == i5 + i6) +" 因为:i5+i6= " + (i5 + i6)); //true
        System.out.println("char计算后,转换类型为:"+ myGetType(i5 + i6));  // int

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型char做加法运算,计算结果是整型的72;
        // i1New72与基本数据类型72比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i1New72=i2+i3 " + (i1New72 == i1 + i3)); //true
        System.out.println("i4New72=i5+i6 " + (i4New72 == i5 + i6)); //true

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,即拆箱后的基本数据类型char做加法运算,计算结果是整型的72;
        // i4New72与基本数据类型72比较的时候也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i4=i5+i6 " + (i4New72 == i5 + i6) +" 因为:i5+i6= " + (i5 + i6)); //true

        Character c = '(';
        System.out.println("字符‘(’的码点值:" + (int)c); //40

        /* Caracter类中有缓存静态内部类CharacterCache;缓存范围:0~127,共128(cache.length)个值
        private static class CharacterCache {
            private CharacterCache(){}

            static final Character cache[] = new Character[127 + 1];

            static {
                for (int i = 0; i < cache.length; i++)
                    cache[i] = new Character((char)i);
            }
        }
         */
    }

(4)Integer


    static void testInt(){
        System.out.println("Boolean类型:");
        Integer i1 = 127;
        Integer i2 = 127;
        Integer i3 = 0;
        Integer i4 = new Integer(127);
        Integer i5 = new Integer(127);
        Integer i6 = new Integer(0);
        Integer i1New = 128;
        Integer i2New = 128;

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为数值在[-128,127]的范围内,使用常量池缓存中的127

        System.out.println("i1New=i2New " + (i1New == i2New));  //false 超过缓存范围,创建新对象了

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池对象127,i4指向堆中对象127

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型int,所以最终是基本数据类型的值作比较
        System.out.println("127=i5+i6 " + (127 == i5 + i6)); //true

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型int;i1与基本数据类型比较的时候也会自动拆箱
        System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型int;
        //i4与i5+i6的基本数据类型int结果比较时,i4也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true

        /* Integer类中有缓存静态内部类IntegerCache;默认缓存范围:-128~127,共256(cache.length)个值;
            但是可通过 java.lang.Integer.IntegerCache.high 修改高位值,例如:设置vm参数 -XX:AutoBoxCacheMax=200 即
            可修改缓存上限为200
        private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];

            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.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_VALUE
                        h = 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() {}
        }
         */
    }

Idea2021通过配置VM options修改Integer缓存上限,具体配置参考:

Idea2021.3.2 设置项目运行参数配置_hnjcxy的博客-CSDN博客Idea2021.3.2 设置运行参数配置:Program arguments 、 Environment variables 和 VM options。1、点击Run -> Edit Configurations2、在打开的窗口可以设置 Program arguments 和 Environment variables 参数,如果需要设置VM参数,请看第三步设置VM参数。设置Program arguments参数时,多个参数中间用空格分开,如:"22" "33" "44"。.https://blog.csdn.net/hnjcxy/article/details/123791208

(5)Long


    static void testLong(){
        System.out.println("Long类型:");
        Long i1 = 127L;
        Long i2 = 127L;
        Long i3 = 0L;
        Long i4 = new Long(127L);
        Long i5 = new Long(127L);
        Long i6 = new Long(0);
        Long i1New = 128L;
        Long i2New = 128L;

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为数值在[-128,127]的范围内,使用常量池缓存中的127L

        System.out.println("i1New=i2New " + (i1New == i2New));  //false 超过缓存范围,创建新对象了

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池对象127L,i4指向堆中对象127L

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型long,所以最终是基本数据类型的值作比较
        System.out.println("127L=i5+i6 " + (127L == i5 + i6)); //true

        //因为 i2+i3 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型long;i1与基本数据类型比较的时候也会自动拆箱
        System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本数据类型long;
        //i4与i5+i6的基本数据类型long结果比较时,i4也会自动拆箱,所以最终是基本数据类型的值作比较
        System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true

        /* long类中有缓存静态内部类ByteCache;缓存范围:-128~127,共256(cache.length)个值
        private static class LongCache {
            private LongCache(){}

            static final Long cache[] = new Long[-(-128) + 127 + 1];

            static {
                for(int i = 0; i < cache.length; i++)
                    cache[i] = new Long(i - 128);
            }
        }
         */

    }

(6)Boolean


    static void testBool(){
        System.out.println("Boolean类型:");
        Boolean i1 = true;
        Boolean i2 = true;
        Boolean i4 = new Boolean("true");
        Boolean i5 = new Boolean("true");

        System.out.println("i1=i2 " + (i1 == i2));  //true 因为i1、i2使用常量池缓存中的true

        System.out.println("i1=i4 " + (i1 == i4)); //false 因为i1指向常量池对象true,i4指向堆中对象true,所以两个对象地址不同

        System.out.println("i4=i5 " + (i4 == i5)); //false 因为i4和i5是堆中两个对象,比较的是两个对象地址

        //因为 i5 与常量true比较时,会自动拆箱为基本数据类型boolean,所以最终比较的是值,不是对象地址
        System.out.println("true=i5+i6 " + (true == i5)); //true

    }

(7)Double 和 Float 没有缓存


    static void testDouble(){
        System.out.println("Double类型:");
        Double i1 = 127.0;
        Double i2 = 127.0;
        Double i3 = 0.0;
        Double i4 = new Double(127.0);
        Double i5 = new Double(127.0);
        Double i6 = new Double(0);

        System.out.println("i1=i2 " + (i1 == i2));  //false 没有缓存,是两个不同的Double类型对象

        //因为 i2+i3 做算术运算+时,会自动拆箱再做加法,所以结果是拆箱后的基本类型double数值127.0,i1与基本数据类型比较时,
        // 也需要拆箱成基本数据类型,最后比较两个基本数据类型127.0的值是否相等
        System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true

        System.out.println("i1=i4 " + (i1 == i4)); //false 没有缓存,是两个不同的Double类型对象

        System.out.println("i4=i5 " + (i4 == i5)); //false 没有缓存,是两个不同的Double类型对象

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是基本数据类型double;最后比较两个基本数据类型127.0的值是否相等
        System.out.println("127.0=i5+i6 " + (127.0 == i5 + i6)); //true
        System.out.println("Double计算后,类型为:"+ myGetType(i5 + i6));  // int

        //因为 i5+i6 做算数运算+时,会自动拆箱再做加法,所以结果是基本数据类型double;i4与i5+i6的基本数据类型结果比较时,
        // i4也会自动拆箱成基本数据类型double,最后是比较基本数据类型的值,而不是比较封装类对象地址
        System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true


    }
测试中用到的判断基本数据类型的方法:
//判断类型
    public static String myGetType(Object o) {
        String type = o.getClass().getSimpleName();
        if ("Integer".equals(type)) {
            return String.valueOf(Integer.TYPE);
        } else if ("Long".equals(type)) {
            return String.valueOf(Long.TYPE);
        } else if ("Float".equals(type)) {
            return String.valueOf(Float.TYPE);
        } else if ("Double".equals(type)) {
            return String.valueOf(Double.TYPE);
        } else if ("Short".equals(type)) {
            return String.valueOf(Short.TYPE);
        } else if ("Byte".equals(type)) {
            return String.valueOf(Byte.TYPE);
        } else if ("Character".equals(type)) {
            return String.valueOf(Character.TYPE);
        } else if ("Boolean".equals(type)) {
            return String.valueOf(Boolean.TYPE);
        }
        return "非基本数据类型!";
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我分别回答您提出的四个问题: 1. Spark k-v结构转换 在Spark中,我们可以使用 `map()`、`flatMap()`、`filter()` 等操作对RDD进行转换。如果我们的数据结构是k-v结构,我们可以使用 `mapValues()`、`flatMapValues()`、`keys()`、`values()` 等操作对key和value进行单独的转换,而不影响另一部分。 例如,我们有一个k-v结构的RDD,其中key是字符串型,value是整数型。我们可以使用以下代码将value加1: ``` val rdd: RDD[(String, Int)] = ??? val result: RDD[(String, Int)] = rdd.mapValues(_ + 1) ``` 2. Spark 数据缓存 当我们在Spark中进行复杂计算时,通常会对中间结果进行缓存,以避免重复计算。Spark提供了两种缓存级别,即内存缓存和磁盘缓存。 我们可以使用 `cache()` 或 `persist()` 方法对RDD进行缓存。默认情况下,Spark将RDD缓存在内存中,但如果内存空间不足,则会将部分数据缓存在磁盘上。我们可以使用 `unpersist()` 方法将缓存的RDD从内存或磁盘中删除。 例如,我们有一个RDD需要进行多次计算,我们可以使用以下代码对其进行缓存: ``` val rdd: RDD[Int] = ??? rdd.cache() val result1 = rdd.reduce(_ + _) val result2 = rdd.map(_ * 2).reduce(_ + _) rdd.unpersist() ``` 3. Spark数据封装逻辑 在Spark中,我们可以使用case class来定义数据封装的逻辑。case class是Scala中的一种特殊,它自动生成了一些方法,包括无参构造函数、getter和setter方法等。 例如,我们有一个存储用户信息的RDD,每个用户包含id、name和age三个属性,我们可以使用以下代码定义一个case class: ``` case class User(id: Int, name: String, age: Int) ``` 然后,我们可以使用 `map()` 方法将RDD中的元素转换为User对象: ``` val rdd: RDD[(Int, String, Int)] = ??? val result: RDD[User] = rdd.map { case (id, name, age) => User(id, name, age) } ``` 4. Spark日期处理机制 在Spark中,我们可以使用Java的日期时间库或者第三方库(如Joda-Time)来处理日期时间。Spark本身提供了一些日期时间处理函数,如 `current_timestamp()`、`date_add()`、`datediff()` 等。 例如,我们有一个存储订单信息的RDD,每个订单包含id、date和price三个属性,其中date是一个字符串型表示日期。我们可以使用以下代码将date转换为日期型,并计算出每个订单距离今天的天数: ``` import java.time.LocalDate val rdd: RDD[(Int, String, Double)] = ??? val today = LocalDate.now() val result = rdd.map { case (id, dateStr, price) => val date = LocalDate.parse(dateStr) val days = java.time.temporal.ChronoUnit.DAYS.between(date, today) (id, days, price) } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值