利用Random的Stream方式生成中文姓名集合

利用Random的Stream方式生成中文姓名集合

今天本来是要研究下Optional判断空集合和抛出异常的问题,结果测试时没有数据,又生成个name1、2、3…觉得太LOW了,想来个中文的,期间也想把Random的Stream与汉字生成结合起来,想采用位运算方式,结果生成出来了,但是有些乱码,最后一步步整出来个这么玩意~ 起码算是对汉字GB2312编码有了些认识,整理了些资料进行了调试,贡献出来~

package com.wenx.demo.study.solution;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * @author Wenx
 * @date 2020/5/10
 */
public class GenerateName {
    public static void main(String[] args) {
        // 1.利用Random的Stream方式生成数据集合,内容最好是中文姓名
        // 2.测试Optional返回集合,为null时抛出异常,但为empty时不报错
        List<String> names = Optional.ofNullable(listName(10))
                .orElseThrow(() -> new RuntimeException());
        names.forEach(System.out::println);
    }

    public static List<String> listName(long size) {
        List<String> names = new ArrayList<>();
        if (size > 0) {
            Random random = new Random();
            names = random.ints(2, 4)
                    .limit(size)
                    .mapToObj(GenerateName::getChineseCharacters)
                    .collect(Collectors.toList());
        }
        return names;
    }

    /**
     * 使用GB2312编码生成汉字:
     * <p>
     * GB2312规定对收录的每个字符采用两个字节表示,
     * 第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位。
     * 可以理解为一张94行94列的区位表,每一行称为一个“区”,每一列称为一个“位”,
     * 共94个区,每区含有94个位,共8836个码位,这种表示方式称为区位码。
     * <p>
     * 区码范围:
     * 01-09区收录除汉字外的682个特殊字符。
     * 10-15区为空白区,没有使用。
     * 16-55区收录3755个一级汉字,按拼音字母排序。
     * 56-87区收录3008个二级汉字,按部首/笔画排序。
     * 88-94区为空白区,没有使用。
     * <p>
     * 位码范围:区码为55时,位码范围为1-89;其他区码,位码范围为1-94。
     * <p>
     * 区位码范围:0101-9494,区号和位号分别转换成十六进制加上0xA0就是GB2312编码。
     * GB2312编码范围:A1A1-FEFE,其中汉字编码范围:B0A1-F7FE,
     * 汉字编码:第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)。
     * 例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。
     */
    public static String getChineseCharacters(int size) {
        final int AREA_CODE_55 = 215;
        Random random = new Random();
        String result = "";
        for (int i = 0; i < size; i++) {
            // 第一字节范围:0xB0~0xF7(对应区号:16~87),最常用的一级汉字(16~55),最后加上0xA0(160)
            // Random.nextInt(n)取值为0~(n-1)不包含n,所以16~55为16+nextInt(55-16)+160
            int r = 176 + random.nextInt(39);
            // 第二字节范围:0xA1~0xFE(对应位号:01~94),最后加上0xA0(160)
            // 当区码为55时位码范围为1~89,其他为1~94
            int c = r == AREA_CODE_55 ? (161 + random.nextInt(89))
                    : (161 + random.nextInt(94));
            byte[] bytes = new byte[]{(byte) r, (byte) c};
            try {
                result += new String(bytes, "GB2312");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值