When does the toUpperCase() method create a new object? - java

public class Child{
public static void main(String[] args){
String x = new String("ABC");
String y = x.toUpperCase();
System.out.println(x == y);
}
}
Output: true
So does toUpperCase() always create a new object?

toUpperCase() calls toUpperCase(Locale.getDefault()), which creates a new String object only if it has to. If the input String is already in upper case, it returns the input String.
This seems to be an implementation detail, though. I didn't find it mentioned in the Javadoc.
Here's an implementation:
public String toUpperCase(Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int firstLower;
final int len = value.length;
/* Now check if there are any characters that need to be changed. */
scan: {
for (firstLower = 0 ; firstLower < len; ) {
int c = (int)value[firstLower];
int srcCount;
if ((c >= Character.MIN_HIGH_SURROGATE)
&& (c <= Character.MAX_HIGH_SURROGATE)) {
c = codePointAt(firstLower);
srcCount = Character.charCount(c);
} else {
srcCount = 1;
}
int upperCaseChar = Character.toUpperCaseEx(c);
if ((upperCaseChar == Character.ERROR)
|| (c != upperCaseChar)) {
break scan;
}
firstLower += srcCount;
}
return this; // <-- the original String is returned
}
....
}

Related

Trashes when trying to see convertion

I've got a problem with this simple class. When I'm trying to convert input String by the Caesar cipher I'm getting another String than thought. What is wrong? And do I implement correctly serialization and deserialization for only String CONTENT? Why output is: [C#58a1a199 rather than DEFGcaf ..? Error when running test is like this: FAILED: ARRAYS FIRST DIFFERED AT ELEMENT[0]; EXPECTED <68> BUT WAS <14>. Why it can't pass this test if we have correct transformation?
HERE IS MY CLASS:
public class TajnyDokument implements Serializable {
public String content;
public transient int howMuchToMove = 3;
private transient String sign;
public transient char[]cypher;
public TajnyDokument(String zawartosc, String podpis) throws IOException {
this.content = zawartosc;
this.sign = podpis;
}
private void writeObject(ObjectOutputStream os) throws IOException
{
szyfruj(content);
os.writeChars(this.content);
//os.writeChars(this.sign);
// os.writeUTF(content);
os.defaultWriteObject();
}
private void readObject ( ObjectInputStream is ) throws IOException , ClassNotFoundException {
content = String.valueOf(is.readChar());
sign = String.valueOf(is.readChar());
is . defaultReadObject ( ) ;
}
public void szyfruj(String dana) throws IOException
{
System.out.println(content);
cypher = dana.toCharArray();
char tmp[] = new char[cypher.length];
char c;
for(int i = 0; i < cypher.length; i++)
{
c = cypher[i];
if((c >'Z' || c < 'A') && (c < 'a' || c > 'z'))
{
throw new IOException();
}
else
{
if(c == 'X')
{
int ilezostalo = (int)'Z' - (int)'X';
tmp[i] = (char)((int)'A' + (howMuchToMove - ilezostalo-1));
System.out.println(tmp[i]);
}
else if(c == 'Y')
{
int ilezostalo = (int)'Z' - (int)'Y';
tmp[i] = (char)((int)'A' + (howMuchToMove - ilezostalo-1));
System.out.println(tmp[i]);
}
else if(c == 'Z')
{
tmp[i] = (char)((int)'A' + (howMuchToMove-1));
System.out.println(tmp[i]);
}
else if(c == 'x')
{
int ilezostalo = (int)'z' - (int)'x';
tmp[i] = (char)((int)'a' + (howMuchToMove - ilezostalo-1));
System.out.println(tmp[i]);
}
else if(c == 'y')
{
int ilezostalo = (int)'z' - (int)'y';
tmp[i] = (char)((int)'a' + (howMuchToMove - ilezostalo-1));
System.out.println(tmp[i]);
}
else if(c == 'z')
{
tmp[i] = (char)((int)'a' + (howMuchToMove-1));
System.out.println(tmp[i]);
}
else
{
tmp[i] = (char)((int)c + howMuchToMove);
System.out.println(tmp[i]);
}
}
}
content = tmp.toString();
if(tmp.toString().equals("DEFGcaf"))
{
this.content = "DEFGcaf";
}
// super.write(tmp)
System.out.println(content);
System.out.println(content);
System.out.println(content);
}
public String getPodpis() {
return sign;
}
public String getZawartosc() {
return content;
}
public static void main(String[] arg) throws IOException
{
TajnyDokument tajny = new TajnyDokument("ABCDzxc", "Piotr Kaczyński");
tajny.szyfruj(tajny.content);
String wynik = tajny.content;
System.out.println(wynik);
}
}
TEST CLASS FOR MY CODE:
public class Punkt2Test {
private ByteArrayOutputStream buffer;
private ObjectOutputStream testOutputStream;
private TajnyDokument testObject;
public Punkt2Test() {
}
#Before
public void setUp() throws IOException {
buffer = new ByteArrayOutputStream();
testOutputStream = new ObjectOutputStream(buffer);
testObject = new TajnyDokument("ABCDzxc", "Piotr Kaczyński");
}
#Test
public void zapisPoprawny() throws IOException, ClassNotFoundException {
testOutputStream.writeObject(testObject);
testOutputStream.flush();
ByteArrayInputStream is = new ByteArrayInputStream(buffer.toByteArray());
byte[] expectedResult = new byte[]{'D', 'E', 'F', 'G', 'c', 'a', 'f'};
byte[] result = new byte[7];
is.skip(101);
is.read(result, 0, 7);
for(int i=0; i<result.length; i++) {
System.out.println(i + " " + (char)result[i] + " " + result[i]);
// System.out.println(result[i]);
}
assertArrayEquals(expectedResult, result);
}
}
You are converting your character array to a string in the wrong fashion. Try:
content = new String(tmp);
Your original code was calling .toString() on an array, which simply calls the Object.toString() implementation. Hence you got something like [C#609a5d54:
[ indicates an array type
C indicates the char type
# separates type from hashcode
609a5d54 was the hashcode (different each time the code runs)
See Object.toString() and Class.getName() for furthed details.
Array are treated as object in java. In your case tmp is array of characters. so when you call toString method on that object it returns you hashcode of that array object.
So Instead writing like
tmp.toString();
write
content = new String(tmp);

EnumMap- Using to detect escape characters

I'm bench marking various ways to escape special characters, out of personal interest.
A colleague suggested that a EnumMap might also be quick in order to check if a character is contained within the Map.
I'm trying the following code and it works using containsValue();
However, can this be made to work with containsKey();?
public static enum EscapeChars {
COLON(':'), SLASH('\\'), QUESTION('?'), PLUS('+'), MINUS('-'), EXCLAMATION(
'!'), LEFT_PARENTHESIS('('), RIGHT_PARENTHESIS(')'), LEFT_CURLY(
'{'), RIGHT_CURLY('}'), LEFT_SQUARE('['), RIGHT_SQUARE(']'), UP(
'^'), QUOTE('"'), TILD('~'), ASTERISK('*'), PIPE('|'), AMPERSEND('&');
private final char character;
EscapeChars(char character) {
this.character = character;
}
public char getCharacter() {
return character;
}
}
static EnumMap<EscapeChars, Integer> EnumMap = new EnumMap<EscapeChars,Integer>(
EscapeChars.class);
static {
for (EscapeChars ec : EscapeChars.values()) {
EnumMap.put(ec, (int)ec.character);
}
}
static void method5_Enum() {
String query2="";
for (int j = 0; j < TEST_TIMES; j++) {
query2 = query;
char[] queryCharArray = new char[query.length() * 2];
char c;
int length = query.length();
int currentIndex = 0;
for (int i = 0; i < length; i++) {
c = query.charAt(i);
if (EnumMap.containsValue((int)c)) {
if ('&' == c || '|' == c) {
if (i + 1 < length && query.charAt(i + 1) == c) {
queryCharArray[currentIndex++] = '\\';
queryCharArray[currentIndex++] = c;
queryCharArray[currentIndex++] = c;
i++;
}
} else {
queryCharArray[currentIndex++] = '\\';
queryCharArray[currentIndex++] = c;
}
} else {
queryCharArray[currentIndex++] = c;
}
}
query2 = new String(queryCharArray, 0, currentIndex);
}
System.out.println(query2);
}
Reference: https://softwareengineering.stackexchange.com/questions/212254/optimized-special-character-escaper-vs-matcher-pattern
I don't believe you would want to because you would first have to convert to an EscapeChars which is the point of having a Map for the lookup. I would suggest that given your usage I would use a Map<Integer, EscapeChars> and use containsKey on this map.

Parameter passing in Java problems

I am new to java, and have been writing a program to check if a given string is periodic or not.A string is not periodic if it cannot be represented as a smaller string concatenated some number of times. Example "1010" is periodic but "1011" is not. Here is my code. It compiles, but the problem is that it tells every string is not periodic. I guess the problem is with the for loop in the isPeriodic function. Please help me get it correct.
import java.io.*;
import java.util.*;
public class Test {
/**
* #param args
*/
public static void main(String[] args) throws java.lang.Exception {
java.io.BufferedReader R = new java.io.BufferedReader
(new java.io.InputStreamReader(System.in));
//String st = R.readLine();
String st = "10101010";
if (isPeriodic(st) == false) {
System.out.println(" Non Periodic");
}
else {
System.out.println("Periodic");
}
}
private static boolean isPeriodic(String s)
{
String temp = s;
int i;
boolean pflag = false;
for ( i = 1; i <= (s.length()/2); i++) {
s = rotateNltr(s,i);
if (s == temp) {
pflag = true;
break;
}
}
return pflag;
}
private static String rotateNltr(String s, int n) {
if( n > s.length()) {
return null;
}
for ( int i = 0; i < n; i++) {
s = leftRotatebyOne(s);
}
//System.out.println(s);
return s;
}
private static String leftRotatebyOne(String s) {
char[] temp = s.toCharArray();
char t = temp[0];
for ( int i = 0 ; i < s.length()-1 ;i++ ) {
temp[i] = temp [i+1];
}
temp[s.length()-1] = t;
String r = new String(temp);
//System.out.println(r);
return r;
}
}
You can't compare objects (and that includes String's) with ==. You have to use the equals method.
Unlike C++ (which I assume is your language of preference) Java doesn't allow comparing String objects with the == operator. Use the equals method to compare the strings.
if (s.equals(temp)) {
pflag = true;
break;
}
In your isPeriodic() the check you are doing is wrong. Do it as below:
if (s.equals(temp)) {
pflag = true;
break;
}
s.equal(temp) alone wont solve the problem, yes it will make the code execute correctly for the input as given in Main method but for 1010, 1011 it wont.
Try using this method :
private static boolean isPeriodic(String s) {
String temp = s;
int i;
boolean pflag = false;
for (i = 1; i <= (s.length() / 2); i++) {
s = leftRotatebyOne(s);
if (s.equals(temp)) {
pflag = true;
break;
}
}
return pflag;
}
This will ensure that for all combination this program works.

how to sort Aplha numeric strings?

I have a list of String characters, They are mix characters that includes special characters too. I want to know how to sort them ascendingly ?
updated
example
aplha1.jpg
aplha10.jpg
2.jpg
3.jpg
4.jpg
aplha5.jpg
What Tom Christiansen (#tchrist) implied, is that for comparing text you should usually use a Collator java.text.Collator, which takes into account real alphabetical order (possibly including locale-specific rules), not just Unicode code-unit lexicographic order.
To do a sorting, you would transform each String into a CollationKey, and then sort the CollationKeys. This is done for efficiency, you could also directly sort the Strings using the Collator, but that would perform worse.
String implements Comparable.
Put your Strings into an ArrayList or array, then call Collections.sort() or Arrays.sort() respectively on them.
Only when there is special needs will you need to use Comparator. Just refrain from rolling out your own "quirk".
I hope this will work for you.
public class AlphanumericSorting implements Comparator<String> {
public int compare(String firstObjToCompare, String secondObjToCompare) {
String firstString = firstObjToCompare.toString();
String secondString = secondObjToCompare.toString();
if (secondString == null || firstString == null) {
return 0;
}
int lengthFirstStr = firstString.length();
int lengthSecondStr = secondString.length();
int index1 = 0;
int index2 = 0;
while (index1 < lengthFirstStr && index2 < lengthSecondStr) {
char ch1 = firstString.charAt(index1);
char ch2 = secondString.charAt(index2);
char[] space1 = new char[lengthFirstStr];
char[] space2 = new char[lengthSecondStr];
int loc1 = 0;
int loc2 = 0;
do {
space1[loc1++] = ch1;
index1++;
if (index1 < lengthFirstStr) {
ch1 = firstString.charAt(index1);
} else {
break;
}
} while (Character.isDigit(ch1) == Character.isDigit(space1[0]));
do {
space2[loc2++] = ch2;
index2++;
if (index2 < lengthSecondStr) {
ch2 = secondString.charAt(index2);
} else {
break;
}
} while (Character.isDigit(ch2) == Character.isDigit(space2[0]));
String str1 = new String(space1);
String str2 = new String(space2);
int result;
if (Character.isDigit(space1[0]) && Character.isDigit(space2[0])) {
Integer firstNumberToCompare = new Integer(Integer.parseInt(str1.trim()));
Integer secondNumberToCompare = new Integer(Integer.parseInt(str2.trim()));
result = firstNumberToCompare.compareTo(secondNumberToCompare);
} else {
result = str1.compareTo(str2);
}
if (result != 0) {
return result;
}
}
return lengthFirstStr - lengthSecondStr;
}
}

String Alternating letters

Im trying to write a segment of code that will request from the user two Strings. How can i write code so that forms a new String by alternating the characters of the two Strings.
Any help is appreciated
Simple "dumb" approach :)
class StringMerge
{
public static String merge(String a, String b)
{
if (a == null || a.length() == 0){ return b; }
else if(b == null || b.length() == 0){ return a; }
else
{
StringBuffer merged = new StringBuffer();
int aIndex = 0;
int bIndex = 0;
while(aIndex < a.length() && bIndex < b.length())
{
merged.append(a.charAt(aIndex));
merged.append(b.charAt(bIndex));
aIndex++;
bIndex++;
}
while(aIndex < a.length())
{
merged.append(a.charAt(aIndex));
aIndex++;
}
while(bIndex < b.length())
{
merged.append(b.charAt(bIndex));
bIndex++;
}
return merged.toString();
}
}
}
A slightly shorter and faster [due to StringBuilder] version of mohaps' approach:
class StringMerge {
public static String merge(final String a, final String b) {
if (a == null || a.length() == 0) {
return b;
} else if (b == null || b.length() == 0) {
return a;
} else {
final int aLength = a.length();
final int bLength = b.length();
final StringBuilder merged = new StringBuilder(aLength + bLength);
for (int i = 0, j = 0; i < aLength && j < bLength; i++, j++) {
merged.append(a.charAt(i)).append(b.charAt(j));
}
if (aLength != bLength) {
if (aLength > bLength) {
merged.append(a.substring(bLength));
} else {
merged.append(b.substring(aLength));
}
}
return merged.toString();
}
}
}
Edit: Added length while creating StringBuilder instance
Pretty much the same as mohaps and shams (smile), but using an array :
static public void main(String...args) {
Scanner scanner = new Scanner(System.in);
System.out.print("String 1 : ");
String s1 = scanner.nextLine();
System.out.print("String 2 : ");
String s2 = scanner.nextLine();
System.out.println("Combined string is : " + mergeStrings(s1, s2));
}
static public String mergeStrings(String a, String b) {
if (a == null) a = "";
if (b == null) b = "";
char[] chars = new char[a.length() + b.length()];
int index = 0, ia = 0, ib = 0;
while (ia<a.length() && ib<b.length()) {
chars[index++] = a.charAt(ia++);
chars[index++] = b.charAt(ib++);
}
while (ia<a.length()) {
chars[index++] = a.charAt(ia++);
}
while (ib<b.length()) {
chars[index++] = b.charAt(ib++);
}
return new String(chars);
}
** UPDATE **
A slightly improvement, added a start position (default to 0) to start merge at a specific position from a. If start is negative, the method will behave as if it were 0. If start is greater than the length of the string a, the string will be padded with spaces until start is reached.
static public String mergeStrings(String a, String b) {
return mergeStrings(a, b, 0);
}
static public String mergeStrings(String a, String b, int start) {
if (a == null) a = "";
if (b == null) b = "";
int len = Math.max(start - a.length(), 0) + a.length() + b.length();
char[] chars = new char[len];
int index = 0, ia = 0, ib = 0;
while (ia<a.length() && ia<start) {
chars[index++] = a.charAt(ia++);
}
while (index<start) {
chars[index++] = ' ';
}
while (ia<a.length() && ib<b.length()) {
chars[index++] = a.charAt(ia++);
chars[index++] = b.charAt(ib++);
}
while (ia<a.length()) {
chars[index++] = a.charAt(ia++);
}
while (ib<b.length()) {
chars[index++] = b.charAt(ib++);
}
return new String(chars);
}
Output :
String 1 : hello
String 2 : world
Combined string is : hweolrllod
Combined merged at 2 : helwloorld
Combined merged at 4 : helloworld
Combined merged at 10 : hello world
Assuming the user enters two strings of the same length:
Make a new, empty string.
Loop...
If Index % 2 == 0, take the character from the second string entered by the user and add it to the empty string.
Otherwise, take the character form the first string and add it to the empty string.
Stop the loop when there are no more characters to add.

Categories