在java中屏蔽信用卡号码

发布于 2024-12-05 14:02:20 字数 2063 浏览 0 评论 0原文

我尝试使用字符“X”屏蔽信用卡号码字符串中的字符。我编写了两个函数,如下所示。第二个函数使用 commons.lang.StringUtils 类。我试图找出它所花费的时间在这两种情况下

public static String maskCCNumber(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        StringBuffer maskedbuf = new StringBuffer(ccnum.substring(0,startlen));
        for(int i=0;i<masklen;i++) {
            maskedbuf.append('X');
        }
        maskedbuf.append(ccnum.substring(startlen+masklen, total));
        String masked = maskedbuf.toString();
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using StringBuffer="+ (endtime-starttime)+" millis");
        return masked;
    }

    public static String maskCCNumberCommons(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        String start = ccnum.substring(0,startlen);
        String end = ccnum.substring(startlen+masklen, total);
        String padded = StringUtils.rightPad(start, startlen+masklen,'X'); 
        String masked = padded.concat(end);
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using Stringutils="+(endtime-starttime)+" millis");
        return masked;
    }

public static void ccNumberMaskingDemo() {
   String mcard1="5555555555554444";
   maskCCNumber(mcard1);
   maskCCNumberCommons(mcard1);
}

,当我运行这个时,我得到了这个结果,

maskCCNumber:=5555XXXXXXXX4444 of :16 size
using StringBuffer=0 millis
maskCCNumber:=5555XXXXXXXX4444 of :16 size
using Stringutils=25 millis

我无法理解为什么commons.StringUtils比第一个函数中的for循环+StringBuffer花费更多的时间。显然我正在使用api,错误的方式..

在这种情况下,有人可以建议如何正确使用这个 api 吗?

I tried to mask the characters in a creditcard number string using character 'X'.I wrote two functions as below .The second function uses commons.lang.StringUtils class .I tried to find the time it takes in both cases

public static String maskCCNumber(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        StringBuffer maskedbuf = new StringBuffer(ccnum.substring(0,startlen));
        for(int i=0;i<masklen;i++) {
            maskedbuf.append('X');
        }
        maskedbuf.append(ccnum.substring(startlen+masklen, total));
        String masked = maskedbuf.toString();
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using StringBuffer="+ (endtime-starttime)+" millis");
        return masked;
    }

    public static String maskCCNumberCommons(String ccnum){
        long starttime = System.currentTimeMillis();
        int total = ccnum.length();
        int startlen=4,endlen = 4;
        int masklen = total-(startlen + endlen) ;
        String start = ccnum.substring(0,startlen);
        String end = ccnum.substring(startlen+masklen, total);
        String padded = StringUtils.rightPad(start, startlen+masklen,'X'); 
        String masked = padded.concat(end);
        long endtime = System.currentTimeMillis();
        System.out.println("maskCCNumber:="+masked+" of :"+masked.length()+" size");
        System.out.println("using Stringutils="+(endtime-starttime)+" millis");
        return masked;
    }

public static void ccNumberMaskingDemo() {
   String mcard1="5555555555554444";
   maskCCNumber(mcard1);
   maskCCNumberCommons(mcard1);
}

When I ran this ,I got this result

maskCCNumber:=5555XXXXXXXX4444 of :16 size
using StringBuffer=0 millis
maskCCNumber:=5555XXXXXXXX4444 of :16 size
using Stringutils=25 millis

I can't understand why commons.StringUtils is taking more time than the for loop+StringBuffer in the first function.Obviously I am using the api ,the wrong way..

Can someone advise how to use this api correctly, in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

苏佲洛 2024-12-12 14:02:20

干得好。干净且可重复使用:

/**
 * Applies the specified mask to the card number.
 *
 * @param cardNumber The card number in plain format
 * @param mask The number mask pattern. Use # to include a digit from the
 * card number at that position, use x to skip the digit at that position
 *
 * @return The masked card number
 */
public static String maskCardNumber(String cardNumber, String mask) {

    // format the number
    int index = 0;
    StringBuilder maskedNumber = new StringBuilder();
    for (int i = 0; i < mask.length(); i++) {
        char c = mask.charAt(i);
        if (c == '#') {
            maskedNumber.append(cardNumber.charAt(index));
            index++;
        } else if (c == 'x') {
            maskedNumber.append(c);
            index++;
        } else {
            maskedNumber.append(c);
        }
    }

    // return the masked number
    return maskedNumber.toString();
}

示例调用:

System.out.println(maskCardNumber("1234123412341234", "xxxx-xxxx-xxxx-####"));
> xxxx-xxxx-xxxx-1234

System.out.println(maskCardNumber("1234123412341234", "##xx-xxxx-xxxx-xx##"));
> 12xx-xxxx-xxxx-xx34

祝你好运。

Here you go. Clean and reusable:

/**
 * Applies the specified mask to the card number.
 *
 * @param cardNumber The card number in plain format
 * @param mask The number mask pattern. Use # to include a digit from the
 * card number at that position, use x to skip the digit at that position
 *
 * @return The masked card number
 */
public static String maskCardNumber(String cardNumber, String mask) {

    // format the number
    int index = 0;
    StringBuilder maskedNumber = new StringBuilder();
    for (int i = 0; i < mask.length(); i++) {
        char c = mask.charAt(i);
        if (c == '#') {
            maskedNumber.append(cardNumber.charAt(index));
            index++;
        } else if (c == 'x') {
            maskedNumber.append(c);
            index++;
        } else {
            maskedNumber.append(c);
        }
    }

    // return the masked number
    return maskedNumber.toString();
}

Sample Calls:

System.out.println(maskCardNumber("1234123412341234", "xxxx-xxxx-xxxx-####"));
> xxxx-xxxx-xxxx-1234

System.out.println(maskCardNumber("1234123412341234", "##xx-xxxx-xxxx-xx##"));
> 12xx-xxxx-xxxx-xx34

Good luck.

黯然 2024-12-12 14:02:20

使用 Apache StringUtils...

String ccNumber = "123232323767"; 

StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);

Using Apache StringUtils...

String ccNumber = "123232323767"; 

StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);
挽清梦 2024-12-12 14:02:20

这是一个基于 StringUtils 的稍微干净的实现,尽管我不确定它与您的实现相比会如何执行。无论如何,“过早优化”的评论仍然非常有效。

    public static String maskNumber(final String creditCardNumber) {
    final String s = creditCardNumber.replaceAll("\\D", "");

    final int start = 4;
    final int end = s.length() - 4;
    final String overlay = StringUtils.repeat(MASK_CHAR, end - start);

    return StringUtils.overlay(s, overlay, start, end);
}

Here's a slightly cleaner implementation based on StringUtils, though I am not sure how it would perform in comparison to your implementations. At any rate, the 'premature optimization' comments remain very valid.

    public static String maskNumber(final String creditCardNumber) {
    final String s = creditCardNumber.replaceAll("\\D", "");

    final int start = 4;
    final int end = s.length() - 4;
    final String overlay = StringUtils.repeat(MASK_CHAR, end - start);

    return StringUtils.overlay(s, overlay, start, end);
}
奢欲 2024-12-12 14:02:20

首先,如果您对这样一个短时间运行的代码进行测量,由于您的 CPU/库/任何提供的最小定时分辨率(这意味着您通常会看到 0ms 或相同的小值),您通常无法获得准确的结果超过)。

其次,也是更重要的是,不要对此进行优化! “过早的优化是万恶之源”,如果您只有几毫秒的时间,那么您想要优化的努力就彻底浪费了。在您甚至不应该考虑优化这种简单的屏蔽方法之前,您必须屏蔽数百万张信用卡。

Firstly, if you make measurements of such a short-running code, you often do not get accurate results due to the minimal timing resolution your CPU/library/whatever provides (which means you usually get to see 0ms or the same small value over and over).

Second and more importantly, do not optimize this! "Premature optimization is the root of all evil" and in a case where you have only a few ms that you want to optimize the effort is thoroughly wasted. You would have to mask millions of credit cards before you should even remotely think about optimizing this simple mask method.

So尛奶瓶 2024-12-12 14:02:20

我知道这不是一个答案,但您可以使用正则表达式并一步解决这个问题

String replaced = originalCreditCardNo.replaceAll("\\b(\\d{4})(\\d{8})(\\d{4})", "$1XXXXXXXX$3");

说明:

  • \b边界有助于检查我们是否是数字的开头(还有其他方法可以做到这一点) ,但在这里就可以了)。
  • (\d{4}) 捕获 4 位数字到组 1 和组 3
  • (\d{8}) 捕获 8 位数字到组 2
  • 在替换中, $1$3包含与组1和组3匹配的内容

I know this is not an answer but you can use regular expression and solve this in one step

String replaced = originalCreditCardNo.replaceAll("\\b(\\d{4})(\\d{8})(\\d{4})", "$1XXXXXXXX$3");

Explanation:

  • The \b boundary helps check that we are the start of the digits (there are other ways to do this, but here this will do).
  • (\d{4}) captures four digits to Group 1 and Group 3
  • (\d{8}) captures eight digits to Group 2
  • In the replacement, $1 and $3 contain the content matched by Groups 1 and 3
一人独醉 2024-12-12 14:02:20

String utils 可能会复制字符串几次。例如,当您运行 padded.concat(end); 时jvm 分配两个连接字符串大小的新字符串并复制它们。如果您使用 StringBuffer,您将保存所有这些副本,因为缓冲区已经分配了位置,并且连接的字符串刚刚复制到那里。对我来说,StringBuffer 更快是有道理的,尽管测量的时间似乎比我预期的要长。

String utils probably copies the string few times. for example when you run padded.concat(end); the jvm allocates new string of the size of the two concat strings and copy them. If you use StringBuffer you saves all those copies as the buffer already has place allocated and the concated string just copied there. make sense to me that the StringBuffer is faster although, the time measured seems rather large then I would expect.

时常饿 2024-12-12 14:02:20

下面的代码将屏蔽 75% 的字符串。

public static String mask(String input) {

    int length = input.length() - input.length()/4;
    String s = input.substring(0, length);
    String res = s.replaceAll("[A-Za-z0-9]", "X") + input.substring(length);


    return res;
}

Below code will mask 75% of the string.

public static String mask(String input) {

    int length = input.length() - input.length()/4;
    String s = input.substring(0, length);
    String res = s.replaceAll("[A-Za-z0-9]", "X") + input.substring(length);


    return res;
}
世界如花海般美丽 2024-12-12 14:02:20

最有可能的是,这是从 apache-commons.jar 文件加载 StringUtils 的时间。不是真正的执行时间。

要计算实际执行时间,请尝试运行多次,看看第二次需要多少毫秒。第 3 到第 100 名将被接受。

无论如何,正如 Frank 所说,不建议优化到这个级别。

Most probably, this is the time of StringUtils being loaded from the apache-commons.jar file. Not the real execution time.

To calculate the real execution time, try to run multiple times and see how much much ms will the 2nd. 3rd up to 100th will take.

Anyway, as Frank said, optimizing to this level is not recommended.

混吃等死 2024-12-12 14:02:20
import java.util.Scanner;
class StringTest{
    public static void main(String ar[]){
        Scanner s=new Scanner(System.in);

        System.out.println("enter account number");
        String name=s.next();
        char a[]=new char[name.length()];
        for(int i=0;i<name.length();i++){
            a[i]=name.charAt(i);
        }
        for(int i=1;i<name.length()-3;i++){
            a[i]='*';
        }

        System.out.println("your account number");
        for(int i=0;i<name.length();i++){
            System.out.print(a[i]);
        }
    }
}
import java.util.Scanner;
class StringTest{
    public static void main(String ar[]){
        Scanner s=new Scanner(System.in);

        System.out.println("enter account number");
        String name=s.next();
        char a[]=new char[name.length()];
        for(int i=0;i<name.length();i++){
            a[i]=name.charAt(i);
        }
        for(int i=1;i<name.length()-3;i++){
            a[i]='*';
        }

        System.out.println("your account number");
        for(int i=0;i<name.length();i++){
            System.out.print(a[i]);
        }
    }
}
真心难拥有 2024-12-12 14:02:20

尽管可读性较差,但您可以在我的机器上使用 Google Caliper 执行此操作,

final char[] ca = in.toCharArray();
Arrays.fill(ca, left, str.length - right, 'X');
return new String(ca)

与使用 StringBuilder 或 StringUtils.overlay + 重复方法的超过 100 纳秒相比,会产生大约 20-25 纳秒。

import static org.apache.commons.lang3.StringUtils.overlay;
import static org.apache.commons.lang3.StringUtils.repeat;

import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;

import com.google.caliper.Param;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class ArrayCopyVsStringBuild extends SimpleBenchmark {

    public static void main(final String[] args) throws Exception {
        Runner.main(ArrayCopyVsStringBuild.class, args);
    }

    @Param({ "1234567890123456", "1234567890" })
    private String input;

    @Param({ "0", "4" })
    private int left;

    @Param({ "0", "4" })
    private int right;

    public void timeArray(final int reps) {
        for (int i = 0; i < reps; i++) {
            final char[] masked = input.toCharArray();
            Arrays.fill(masked, left, masked.length - right, 'X');
            final String x = new String(masked);
            x.toString();
        }
    }

    public void timeStringBuilder(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            for (int z = 0; z < input.length() - left - right; ++z) {
                b.append('X');
            }
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtils(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            b.append(repeat('x', input.length() - left - right));
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtilsOverlay(final int reps) {
        for (int i = 0; i < reps; i++) {
            final int maskLength = input.length() - left - right;
            final String x = overlay(input, repeat('x', maskLength), left,
                    maskLength + left);
            x.toString();
        }
    }
}

Although less readable you can do this

final char[] ca = in.toCharArray();
Arrays.fill(ca, left, str.length - right, 'X');
return new String(ca)

Using Google Caliper on my machine would yield about 20-25 ns compared to over 100ns with StringBuilder or StringUtils.overlay + repeat approaches.

import static org.apache.commons.lang3.StringUtils.overlay;
import static org.apache.commons.lang3.StringUtils.repeat;

import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;

import com.google.caliper.Param;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class ArrayCopyVsStringBuild extends SimpleBenchmark {

    public static void main(final String[] args) throws Exception {
        Runner.main(ArrayCopyVsStringBuild.class, args);
    }

    @Param({ "1234567890123456", "1234567890" })
    private String input;

    @Param({ "0", "4" })
    private int left;

    @Param({ "0", "4" })
    private int right;

    public void timeArray(final int reps) {
        for (int i = 0; i < reps; i++) {
            final char[] masked = input.toCharArray();
            Arrays.fill(masked, left, masked.length - right, 'X');
            final String x = new String(masked);
            x.toString();
        }
    }

    public void timeStringBuilder(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            for (int z = 0; z < input.length() - left - right; ++z) {
                b.append('X');
            }
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtils(final int reps) {
        for (int i = 0; i < reps; i++) {
            final StringBuilder b = new StringBuilder(input.length());
            b.append(input.substring(0, left));
            b.append(repeat('x', input.length() - left - right));
            b.append(input.substring(input.length() - right));
            final String x = b.toString();
            x.toString();
        }
    }

    public void timeStringUtilsOverlay(final int reps) {
        for (int i = 0; i < reps; i++) {
            final int maskLength = input.length() - left - right;
            final String x = overlay(input, repeat('x', maskLength), left,
                    maskLength + left);
            x.toString();
        }
    }
}
夏了南城 2024-12-12 14:02:20
public class MaskCreditCard {

static void creditcard(String cc) {

    StringBuffer s = new StringBuffer();

    if (cc.length() <= 4) {
        System.out.println(cc);
    } else if (cc.length() > 16) {
        System.out.println("Give a valid 16 digit CC number");
    }

    else {
        for (int i = cc.length() - 4; i > 0; i--) {
            s.append("#");
        }
        System.out.println(s + "" + cc.substring(cc.length() - 4));
    }
}

public static void main(String[] args) {

    creditcard("11111111111111111111111111111111");

}

}
public class MaskCreditCard {

static void creditcard(String cc) {

    StringBuffer s = new StringBuffer();

    if (cc.length() <= 4) {
        System.out.println(cc);
    } else if (cc.length() > 16) {
        System.out.println("Give a valid 16 digit CC number");
    }

    else {
        for (int i = cc.length() - 4; i > 0; i--) {
            s.append("#");
        }
        System.out.println(s + "" + cc.substring(cc.length() - 4));
    }
}

public static void main(String[] args) {

    creditcard("11111111111111111111111111111111");

}

}
蓝天 2024-12-12 14:02:20
String existingCCNmbr = "4114360123456785";
    int i = 0;
    StringBuffer temp = new StringBuffer();
    while(i < (existingCCNmbr .length())){
        if(i > existingCCNmbr .length() -5){
            temp.append(existingCCNmbr.charAt(i));
        } else {
            temp.append("X");
        }
        i++;
    }
       System.out.println(temp);
       }

输出:XXXXXXXXXXXX6785

String existingCCNmbr = "4114360123456785";
    int i = 0;
    StringBuffer temp = new StringBuffer();
    while(i < (existingCCNmbr .length())){
        if(i > existingCCNmbr .length() -5){
            temp.append(existingCCNmbr.charAt(i));
        } else {
            temp.append("X");
        }
        i++;
    }
       System.out.println(temp);
       }

Out put : XXXXXXXXXXXX6785

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文