我试图使用字符'X'来掩盖信用卡号码字符串中的字符。我写了两个函数如下。第二个函数使用commons.lang.StringUtils
类。我试图找到两种情况下的时间< / p>
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吗?
答案 0 :(得分:16)
你走了。清洁和可重复使用:
/**
* 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
祝你好运。
答案 1 :(得分:8)
这是一个基于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);
}
答案 2 :(得分:7)
使用Apache StringUtils ......
String ccNumber = "123232323767";
StringUtils.overlay(ccNumber, StringUtils.repeat("X", ccNumber.length()-4), 0, ccNumber.length()-4);
答案 3 :(得分:5)
首先,如果你对这种短时间运行的代码进行测量,由于你的CPU /库/提供的最小时序分辨率,你经常得不到准确的结果(这意味着你通常会看到0ms或相同的小价值一遍又一遍。)
其次,更重要的是,不要优化这个! “过早优化是所有邪恶的根源”,如果你只有几毫秒,你想要优化努力就彻底浪费了。在你甚至应该远程考虑优化这种简单的掩模方法之前,你必须屏蔽数百万张信用卡。
答案 4 :(得分:2)
最有可能的是,这是从StringUtils
文件加载apache-commons.jar
的时间。不是真正的执行时间。
要计算实际执行时间,请尝试多次运行并查看第二个多少ms。第3到第100将采取。
无论如何,正如弗兰克所说,不建议优化到这个水平。
答案 5 :(得分:2)
String utils可能会复制字符串几次。例如,当你运行padded.concat(结束); jvm分配两个concat字符串大小的新字符串并复制它们。如果使用StringBuffer,则保存所有这些副本,因为缓冲区已经分配了位置,并且在那里复制了连接的字符串。让我觉得StringBuffer更快,虽然测量的时间看起来比我想象的要大。
答案 6 :(得分:2)
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]);
}
}
}
答案 7 :(得分:1)
虽然可读性较差,但您可以这样做
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 + repeat方法则超过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();
}
}
}
答案 8 :(得分:1)
我知道这不是答案,但你可以使用正则表达式并一步解决这个问题
String replaced = originalCreditCardNo.replaceAll("\\b(\\d{4})(\\d{8})(\\d{4})", "$1XXXXXXXX$3");
说明:
答案 9 :(得分:0)
下面的代码将屏蔽字符串的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;
}
答案 10 :(得分:-1)
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