Suppose I have the following implementations
private static String encryptPassword(String password) {
String encryptedPassword = "";
char[] chars = password.toCharArray();
for (char c : chars) {
encryptedPassword = encryptedPassword.concat(String.valueOf( c));
}
return encryptedPassword;
}
private static String decryptPassword(String encryptedPassword) {
String decryptedPassword = "";
char[] chars = encryptedPassword.toCharArray();
for (char c : chars) {
decryptedPassword = decryptedPassword.concat(String.valueOf(--c));
}
return decryptedPassword;
}
These methods do very simple stuff that it will increase each character in a string by 1 and this process is considered as encryption. As a contrast, the process of decryption will decrease the value.
I can see that these two methods are pretty much the same, except the unary operators.
How can I generalize these two methods?
Furthermore, I also prefer streaming processing to looping. If you have any ideas regarding this point please posting as well.
CodePudding user response:
Define a enum to specify operaiton type, based on the enum you can apply business logic.
private static enum OperationType {
ENCRYPTION(1), DECRYPTION(-1);
int val;
private OperationType(int val) {
this.val = val;
}
}
private static String process(final String data, final OperationType operationType) {
final char[] chars = data.toCharArray();
final StringBuilder builder = new StringBuilder();
for (char ch : chars) {
builder.append(String.valueOf(ch operationType.val));
}
return builder.toString();
}
To work with streams, you can use string chars method like below.
Stream<Character> charStream = data.chars().mapToObj(i->(char)i);
CodePudding user response:
The difference between the two methods encryptPassword
and decryptPassword
is the value that you are adding to each char
in the String
. Therefore I suggest adding a third method that takes two parameters: the first is the String
to encrypt (or decrypt) and the second is the value to add to each char
. In the below code, I called this third method adjustPassword
.
As described in the book Java by Comparison I suggest keeping methods encryptPassword
and decryptPassword
and have those methods call method adjustPassword
with the appropriate value. That way, when you want to encrypt or decrypt a password, you don't need to remember what value to pass for the required operation.
Explanations after the code.
public class Solution {
private static String encryptPassword(String password) {
return adjustPassword(password, 1);
}
private static String decryptPassword(String encryptedPassword) {
return adjustPassword(encryptedPassword, -1);
}
private static String adjustPassword(String password, int adjustment) {
StringBuilder sb = new StringBuilder(password.length());
password.chars()
.map(c -> c adjustment)
.forEach(i -> sb.append((char) i));
return sb.toString();
}
public static void main(String[] args) {
String password = "George";
System.out.println("Original: " password);
String encrypted = encryptPassword(password);
System.out.println("Encrypted: " encrypted);
System.out.println("Decrypted: " decryptPassword(encrypted));
}
}
Running the above code produces the following output:
Original: George
Encrypted: Hfpshf
Decrypted: George
- Since Java 9, class
String
has methodchars()
which returns anIntStream
sincechar
is essentially anint
. - Class
StringBuilder
has overloadedappend
methods. In theforEach
method, the type of the method parameter, i.e.i
, isint
, hence the cast tochar
, otherwise methodadjustPassword
would return aString
that only contained digits.