替换和转换字符串

时间:2016-08-10 20:21:37

标签: java

有一个代码可以解密引入字符串的地方,然后用双号解密,字母可以是a到j,分别是a = 0,b = 1 ... j = 9。 该程序有效,我想知道也许有一种最简单的方法来实现这一目标吗?我是java的新手,目前还不知道所有的功能。 代码:

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.Double;
public class Decrypt 
{   
    private static String conversionTable[][] = {
        {"a", "0"},
        {"b", "1"},
        {"c", "2"},
        {"d", "3"},
        {"e", "4"},
        {"f", "5"},
        {"g", "6"},
        {"h", "7"},
        {"i", "8"},
        {"j", "9"},
    };
    private static Scanner scanner;

    public static double decrypt(String encryptedNumber) 
    {
        String c = "";
        int i = 0;
        String[] s = encryptedNumber.split("");

        for(int j = 0; j < 2; j++) {
            if(c.length() == s.length)
                break;

            for(int k = 0; k < 9; k++) {
                if(c.length() == s.length)
                    break;
                if(conversionTable[k][j].equalsIgnoreCase(s[i])){
                     c += k;
                        i++;
                }else if(s[i].equalsIgnoreCase(".")){
                    c += ".";
                    i++;
                }
            }
            j--;
        }

        double d = Double.parseDouble(c);
        return d;
    }

    public static void main(String arg[])
    {   
        scanner = new Scanner(System.in);
        System.out.println("Enter the string to decrypt:");
        String input=scanner.next();
        System.out.println("Number after decryption is:"+decrypt(input));
    }
}

1 个答案:

答案 0 :(得分:0)

从加密的角度来看,您所描述的是substitution cipher。我甚至不再考虑这种加密,更像是编码(参见here)。

你有字符串添加到字符串。当你做

之类的事情
c += k;

Java实际上在做什么是创建一个新的String对象并将c中的指针更改为该新对象。多年来,JVM在创建和丢弃短期对象时变得更好,但这仍然非常低效。请尝试使用StringBuilder

您还通过convertTable执行了sequential search,这意味着您的整个算法都是O(n ^ 2)操作(请参阅here)(对于挑剔者来说,它实际上是O(m *) n)但这对我来说足够接近了)。与这样一个小桌子完全无关,但如果可能的话,避免做那样的事情。另外,当语言中的某些东西想要为你做这件事时(这将是一个反复出现的主题),自己写它是没有意义的。您的项目是有序的,因此我们可以利用Arrays中的一个binarySearch()实现。我会稍微设想一下这个用法,但这只是为了说明。

您可以利用增强的for循环来迭代大多数列表。我甚至会说,如果你不能使用增强型for循环,那么你应该认真考虑一个while循环。

避免在交换机以外的任何地方使用break语句。大多数人会认为他们和goto在同一条船上。

为变量提供更具描述性的名称。你未来的自我会感谢你。

因此,根据我所概述的更改,我们最终得到以下decrypt()方法:

public static double decrypt(String encryptedNumber) {
   StringBuilder builder = new StringBuilder();
   int i = 0;
   String[] encNumElements = encryptedNumber.toLowerCase().split("");
   for (String element : encNumElements) {
      int foundAt = Arrays.binarySearch(conversionTable, new String[]{element, ""}, new Comparator<String[]>() {
            @Override
            public int compare(String[] arg0, String[] arg1) {
               return arg0[0].compareTo(arg1[0]);
            }               
      });
      if (foundAt >= 0) {
         builder.append(conversionTable[foundAt][1]);
      } else {
         // assuming a decimal point here since it's not on the list
         builder.append('.');
      }
   }

   double d = Double.parseDouble(builder.toString());
   return d;
}

这只是好一点。如果我真的想做这样的事情,比较器将是一个单独的类,但这可以用于说明。

从编码的角度来看,这里有一个查找表。简单的实现是Map。传统上,初始化静态查找映射有点难看,但请查看i_am_zero的答案here,以便用Java 8进行更简洁的方式。映射是一种自然搜索结构,因此顺序并不重要。它还具有很好的副作用,即将小数点放入Map中,从而消除if语句。

   private static final Map<String, String> conversionMap = Stream.of(
         new SimpleEntry<>("a", "0"),
         new SimpleEntry<>("b", "1"),
         new SimpleEntry<>("c", "2"),
         new SimpleEntry<>("d", "3" ),
         new SimpleEntry<>("e", "4"),
         new SimpleEntry<>("f", "5"),
         new SimpleEntry<>("g", "6"),
         new SimpleEntry<>("h", "7" ),
         new SimpleEntry<>("i", "8"),
         new SimpleEntry<>("j", "9"),
         new SimpleEntry<>(".", "."))
         .collect(Collectors.toMap((se) -> se.getKey(), (se) -> se.getValue()));

   public static double decrypt(String encryptedNumber) {
      StringBuilder builder = new StringBuilder();
      String[] encNumElements = encryptedNumber.toLowerCase().split("");
      for (String element : encNumElements) {         
            builder.append(conversionMap.get(element));
      }

      double d = Double.parseDouble(builder.toString());
      return d;
   }

这样的事情是我会在一般情况下停下来的地方。但是您的查找列表是一系列整数序列的字符。 Java实际上确实将原始字符视为整数,因此您可以对它们进行数学运算。 String甚至为我们提供了一个从String中获取字符的方法,因此我们可以直接遍历它们。我们必须再次处理if中的小数点,但它可以让我们完全摆脱查找表。

   public static double decrypt(String encryptedNumber) {
      StringBuilder builder = new StringBuilder();
      for (char ch : encryptedNumber.toLowerCase().toCharArray()) {
         if (ch == '.') {
            builder.append('.');
         } else {
            builder.append(ch - 'a');
         }
      }
      return Double.parseDouble(builder.toString());
   }