持续更新一些编码中遇到的奇技淫巧

文章介绍了如何在SQL中使用ASCII码交换字段中的f和m,并强调了使用安全的字符串比较方法防止TimingAttack。此外,还讨论了提高单元测试可测性的两个案例,包括将随机数生成改为可控制的输入和使用Executor接口进行生产者消费者模式的测试。
摘要由CSDN通过智能技术生成
  1. SQL中灵活使用ASCII码

请你编写一个 SQL 查询来交换所有的 'f''m' (即,将所有 'f' 变为 'm' ,反之亦然),仅使用 单个 update 语句 ,且不产生中间临时表。

注意,你必须仅使用一条 update 语句,且 不能 使用 select 语句。

解答:

UPDATE Salary SET sex = char(ascii('m') + ascii('f') - ascii(sex));

  1. safeEqual防止Timing Attack

源码:

boolean safeEqual(String a, String b) {

if (a.length() != b.length()) {

return false;

}

int equal = 0;

for (int i = 0; i < a.length(); i++) {

equal |= a.charAt(i) ^ b.charAt(i);

}

return equal == 0;

}

原理解答:

这种手段可以让调用 safeEquals("abcdefg", "fjkmln") (只有首位不相同)和调用 safeEquals("abcdefg","abcdefg") (两个完全相同的字符串)的所耗费的时间一样。防止通过大量的改变输入并通过统计运行时间来暴力破解出要比较的字符串。

  1. 提高可测性

案例一

优化前:

该代码由于产生的结果为随机数,导致无法判断结果是否正确无法测试

public int a(){
    return RandomGenerator.getDefault().nextInt(1000)+1;
}

优化后:

Supplier是一个java8提供的函数接口,无参数返回值类型为T类型,单元测试可通过传入常量来测试该方法,线上可通过传入()->RandomGenerator.getDefault().nextInt(1000)参数运行该方法

public int a(Supplier<Ingeter> supplier){
    return supplier.get()+1;
}

测试代码:

public void testa(){
    assert a(()->1) == 2;
}

案例二

优化前:

该代是一个典型的生产者消费传递内容代码,存在异步过程无法进行测试

public <T> void producerConsuer(Consumer<Consumer<T>> producer,Consumer<Supplier<T>> consumer){
    BlockingQueue<T> blockQueue = new LinkedBlockingQueue<>();
    new Thread(()->producer.accept(blockQueue::add)).start();
    new Thread(()->consumer.accept(()->{
        try{
            return blockQueue.take();
        }catch(InterrutedException e){
            throw new RuntimeException(e);
        }
    })).start();
}

优化后:

增加一个jdk本身提供的Executor接口类,该接口类在单元测试时候我们可以传递一个同步状态Executor,线上可传入一个线程Executor运行该方法

public <T> void producerConsumer(Executor executor,
Consumer<Consumer<T>> producer, Consumer<Supplier<T>> consumer){
    BlockingQueue<T> blockQueue = new LinkedBlockingQueue<>();
    new Thread(()->producer.accept(blockQueue::add)).start();
    new Thread(()->consumer.accept(()->{
        try{
            return blockQueue.take();
        }catch(InterrutedException e){
            throw new RuntimeException(e);
        }
    })).start();
}

单元测试用例:

public void producerConsumer(){
    producerConsumer(Runnable::run,
    Consumer<Consumer<T>> producer->{
        producer.accept(1);
        producer.accept(2);
        },
    consumer->{
        assert consumer.get() == 1;
        assert consumer.get() == 2;
    }
);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值