[英]masking a creditcard number in java
我尝试使用字符“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 loop+StringBuffer 花费更多的时间。显然我正在使用 api,错误的方式..
在这种情况下,有人可以建议如何正确使用这个 api 吗?
干得好。 清洁和可重复使用:
/**
* 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
祝你好运。
使用 Apache StringUtils...
String ccNumber = "123232323767";
StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);
这是一个基于 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);
}
首先,如果您测量这样一个短时间运行的代码,由于您的 CPU/库/任何提供的最小时间分辨率(这意味着您通常会看到 0ms 或相同的小值),您通常不会得到准确的结果。超过)。
其次,更重要的是,不要优化这个! “过早的优化是万恶之源” ,如果您只有几毫秒的时间想要优化,那么您的努力就完全浪费了。 在远程考虑优化这种简单的屏蔽方法之前,您必须屏蔽数百万张信用卡。
我知道这不是答案,但您可以使用正则表达式并一步解决此问题
String replaced = originalCreditCardNo.replaceAll("\\b(\\d{4})(\\d{8})(\\d{4})", "$1XXXXXXXX$3");
解释:
下面的代码将屏蔽 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;
}
String utils 可能会复制字符串几次。 例如当你运行 padded.concat(end); jvm分配两个concat字符串大小的新字符串并复制它们。 如果您使用 StringBuffer ,您将保存所有这些副本,因为缓冲区已经分配了位置,并且连接的字符串刚刚复制到那里。 对我来说,StringBuffer 更快是有道理的,尽管测量的时间似乎比我预期的要大。
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]);
}
}
}
很可能,这是从apache-commons.jar
文件加载StringUtils
的时间。 不是真正的执行时间。
要计算真正的执行时间,请尝试运行多次,看看第二次会有多少毫秒。 第 3 到第 100 将采取。
无论如何,正如弗兰克所说,不建议优化到这个级别。
虽然可读性较差,但您可以这样做
final char[] ca = in.toCharArray();
Arrays.fill(ca, left, str.length - right, 'X');
return new String(ca)
在我的机器上使用 Google Caliper 将产生大约 20-25 ns,而使用 StringBuilder 或 StringUtils.overlay + 重复方法则超过 100ns。
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();
}
}
}
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");
}
}
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.