Match mixed list elements with scanner - java

let's say I have a mixed list (String & integer data types) 100's of lines long.
i.e.
Lines=
<Thanks For 44 55>
<Helping Me 43 66>
etc...
I want to use the scanner class to match the two strings (& extract the corresponding numbers as well).
How can I write an isolate method to perform this.
The goal is to feed the two corresponding integer values into a separate calculate method.
Here's what I have.
private List<String> lines = new ArrayList<String>();
public void isolate( String s, String l){
if(String s = this.line.matches(".s*") && String l=this.line.matches(".l*")){
lineNew = lines[s][l];
//// extract the integer values (index 2, index 3) from linesNew here }
}

You've stated in comments:
Updated the specifics above, it's a list with integer & string datatypes.
And I beg to differ, that no, it's a List of String, period. The String might hold representations of ints and sub strings, but they're all held within a String. The key to a decent solution is to not do this, not use String to represent something which logically could be represented in a much sounder fashion. So,...
Create a custom class, one with two private String and two private int fields,
with getters and setters, constructors,...
Make it implement Comparable<...> even if it one or both of the numeric fields represents its "natural" order.
When you read in your line with the Scanner, parse the line into the constituent field types of this custom class of yours, and create an object with it.
Then place it into your List<MyCustomClass>.
Do this and creating your methods becomes trivial.
Consider using a 2nd inner Scanner, one for the line, and that helps you parse the line into two Strings and two ints. Be sure to close this inner Scanner with each iteration of the loop so as not to waste resources.

Related

Java very long string compare seems not to work

Update:
Using your suggestions in checking between strings, I found out that the difference is on the arrangement of some fields since these strings are actually JSON strings.
Example:
the field username: johndoe#dummy.com on string1 is located at the beginning, but is located somewhere in the middle in string2.
I wonder if there is a way to check or compare 2 json objects regardless of the arrangement of their fields/properties... as long as their contents (field values) are the same.
What I tried:
private boolean sameJsonObject(Object o1, Object o2) throws IOException {
if (o1 == null || o2 == null) {
return false;
}
JsonNode json1 = mapper.readTree(mapper.writeValueAsString(o1));
JsonNode json2 = mapper.readTree(mapper.writeValueAsString(o2));
return json1.equals(json2);
}
this works but I am sure that this can be improved.
Original Problem:
I would like to check if two strings are equal, but these strings are really long that it cannot be set to a variable/string object and would get string constant too long.
I know that there is equals(), equalsIgnoreCase(), and StringUtils.equals(s1, s2) but none of these seems to work.
The strings that I am comparing came from two different sources and comparing it manually get the same results (I mean the contents are the same).
I tried to post the sample strings here but I can't. The size of each string to compare is more than 30k (170k each string).
btw, these strings are actual data (json) and they are really huge and I want to test its equality (content).
Is there a way to do the checking in java?
Thanks!
The simple answer is: compare the two strings char by char.
In other words: most likely, the built-in Java string compare methods are correct, leading to: your input strings aren't equal. It is extremely unlikely that equal strings result in equals() giving false.
Thus the reasonable first option is: change your comparison code so that it:
iterates the first string, char by char
fetches the corresponding char from the second string
compares those (either "full" equals, or ignoring case)
on mismatch: print out the index and the two different chars (where you ensure to print something like "<" + thatChar + ">" just to ensure that non-printable chars, or maybe using Character.getNumericValue())
So, the answer here is basically to enable yourself to do proper debugging.
btw, these strings are actual data (json) and they are really huge and
I want to test its equality (content).
If these are JSON data, don't compare them with String.
Use a JSON library (Jackson, GSON or anything)to represent these data and also to compare them (equals() is generally overridden).It will compare them more cleanly and more specifically by considering or ignoring things like whitespace, node order and so forth...
You can find some examples here.
You could consider more particularly SkyScreamer library that provides multiple flavors to compare JSON. For example this JSONAssert.assertEquals() overload :
public static void assertEquals(org.json.JSONArray expected,
org.json.JSONArray actual,
JSONCompareMode compareMode)
throws org.json.JSONException
where you can specify a JSONCompareMode object such as JSONCompareMode.LENIENT.
170k is not too large for a String, though it is large for a string literal in source code.
Load your two strings from files that contain them, and compare in the normal way using equals.
You mention that the strings are not text but JSON. For most purposes, you'd want to normalize your json (make the whitespace, property order and punctuation the same).

Parsing natural text to array

How can I parse natural strings like these:
"10 meters"
"55m"
Into instances of this class:
public class Units {
public String name; //will be "meters"
public int howMuch; //will be 10 or 55
}
P.S. I want to do this with NLP libraries, I'm really a noob in NLP and sorry for my bad english
It is possible, but I recommend you don't do this. An array usually holds only hold one type of data structures, so it cannot hold an int and a string at the same time. If you did do it, you would have to do Object[][]
You could use the following algorithm:
Separate the text into words by looping through each character and breaking off a new word each time you encounter a space: this can be stored in a String array. Make sure that each word is stored lowercase.
Store a 2-dimensional String array as a database of all the units you want to recognize: this could be done with each sub-array representing one unit and all its equivalent representations: for example, the sub-array for meters might look like {"meter","meters","m"}.
Make two parallel ArrayLists: the first representing all numerical values and the second representing their corresponding units.
Loop through the list of words from step 1: for each word, check if it is in the format nubmer+unit (without an adjoining space). If so, then split the number off and put it in the first ArrayList. Then, find the unabbreviated unit corresponding with the abbreviated unit given in the text by referring to the 2-dimensional string array (this should be the first index of the subarray). Add this unit to the second ArrayList. Finally, if the word is a single number, check if the next word corresponds with any of the units; if it does, then find its unabbreviated unit (the first index of the sub-array). Then add the number and its unit to their respective ArrayLists.

Java concatenate strings vs static strings

I try to get a better understanding of Strings. I am basically making a program that requires a lot of strings. However, a lot of the strings are very, very similar and merely require a different word at the end of the string.
E.g.
String one = "I went to the store and bought milk"
String two = "I went to the store and bought eggs"
String three = "I went to the store and bought cheese"
So my question is, what approach would be best suited to take when dealing with strings? Would concatenating 2 strings together have any benefits over just having static strings in, say for example, performance or memory management?
E.g.
String one = "I went to the store and bought "
String two = "milk"
String three = "cheese"
String four = one + two
String five = one + three
I am just trying to figure out the most optimal way of dealing with all these strings. (If it helps to put a number of strings I am using, I currently have 50 but the number could surplus a huge amount)
As spooky has said the main concern with the code is readability. Unless you are working on a program for a phone you do not need to manage your resources. That being said, it really doesn't matter whether you create a lot of Strings that stand alone or concatenate a base String with the small piece that varies. You won't really notice better performance either way.
You may set the opening sentence in a string like this
String openingSentence = "I went to the store and bought";
and alternate defining each word alone, by defining one array of strings like the following ::
String[] thingsToBeBought = { "milk", "water", "cheese" .... };
then you can do foreach loop and concatenate each element in the array with the opening sentence.
In Java, if you concatenate two Strings (e.g. using '+') a new String is created, so the old memory needs to be garbage collected. If you want to concatenate strings, the correct way to do this is to use a StringBuilder or StringBuffer.
Given your comment about these strings really being URLs, you probably want to have a StringBuilder/StringBuffer that is the URL base, and then append the suffixes as needed.
Performance wise final static strings are always better as they are generated during compile time. Something like this
final static String s = "static string";
Non static strings and strings concatenated as shown in the other example are generated at runtime. So even though performance will hardly matter for such a small thing, The second example is not as good as the first one performance wise as in your code :
// not as good performance wise since they are generated at runtime
String four = one + two
String five = one + three
Since you are going to use this string as URL, I would recommend to use StringJoiner (in case your are using JAVA 8). It will be as efficient as StringBuilder (will not create a new string every time you perform concatenation) and will automatically add "/" between strings.
StringJoiner myJoiner = new StringJoiner("/")
There will be no discernable difference in performance, so the manner in which you go about this is more a matter of preference. I would likely declare the first part of the sentence as a String and store the individual purchase items in an array.
Example:
String action = "I went to the store and bought ";
String [] items = {"milk", "eggs", "cheese"};
for (int x = 0; x< items.length; x++){
System.out.println(action + items[x]);
}
Whether you declare every possible String or separate Strings to be concatenated isn't going to have any measurable impact on memory or performance in the example you give. In the extreme case of declaring truly large numbers of String literals, Java's native hash table of interned Strings will use more memory if you declare every possible String, because the table's cached values will be longer.
If you are concatenating more than 2 Strings using the + operator, you will be creating extra String objects to be GC'd. For example if you have Strings a = "1" and b = "2", and do String s = "s" + a + b;, Java will first create the String "s1" and then concatenate it to form a second String "s12". Avoid the intermediate String by using something like StringBuilder. (This wouldn't apply to compile-time declarations, but it would to runtime concatenations.)
If you happen to be formatting a String rather than simply concatenating, use a MessageFormat or String.format(). It's prettier and avoids the intermediate Strings created when using the + operator. So something like, String urlBase = "http://host/res?a=%s&b=%s"; String url = String.format(urlBase, a, b); where a and b are the query parameter String values.

How do you save a custom linked list (double linked list?) on to a file?

I have a linked list called CalendarLinkedList which the data members are all user defined,
GregorianCalendar date;
Monetary savings;
Monetary loss;
Memo memo;
Debt debt;
int counter;
CalendarLinkedList next;
CalendarLinkedList previous;
Monetary objects consist of a double and a String array
double value;
String[] type;
public Monetary()
{
setValue(0);
type = new String [50];
}
Memo consists only of String
String writing;
public Memo()
{
writing = "";
}
Debt is an extension of Monetary with one more double value and two Gregorian Calendars.
Is there anyway which I can store this on a text file?
It will be better if you guys tell me how to load it from the text file after saving also.
I know the codes are very inefficient but I wanted to at least create the link list without any help. I've been stuck here for a couple of while and finally came to this place for help.
If you have to use text files, then what I would suggest is to find some sort of scheme to correspond lines to attributes and from that scheme, rebuild the linked list as you read them for file.
As the scheme, look at this small example. Imagine you only wanted to save a list of Monetary. What you could do was, for each item on the list, you would save, in each line:
The value of the variable 'value'
The length of the array of strings (let's say n strings)
n strings
Now, when reading the file, you would firstly create an empty Monetary item, and you would read the first line of the text file to fill 'value'. Then, you would read the value of n and it would indicate you how many lines you still would have to read to fill the string array. You would do this procedure till you found an EOF.
Now, what I've said applies only for the case of saving an instance of Monetary. For you linked list, you would do the same, but for more objects. Was I clear enough?

How do I make an array from inputted information (i.e. names) and then use it as objects within the code?

I've been reading up on it, but every question I've found has asked for slightly different things, such as only wanting a single letter for their array, or in a different language (I'm new and only learning java at the moment), so here I am.
I want to set up an array that uses the user's input for their names.
What I have so far is this, I'm assuming this is the declaration line, where later I use an input line to define a value within the array (which I also am unsure how to do)
String[] array = {"name"};
But I don't know how to for example print.out the object or keep up with which name will be what value. I appreciate your time taken to teach me!
EDIT for further clarification. I'm trying to write up a small app that asks the user for numerous names, addresses, and phone numbers (Type name -> Type name's address -> type name's phone number, ask if they want to add another person, if yes then go back to asking for another name)
I am unsure how to set up a String array or how to use it throughout. However, thanks to your input and coming back after some fresh air, I have a better idea how to word it for google. Thank you guys for your help, even if it was just to gesture a better articulated question.
An array is a sequence of values. You have created an array of Strings that is one String long. To access the value at a specific of an array, use array subscript notation: the name of the array followed by a pair of square brackets ([]) with the index in between them.
String[] anArrayOfStrings = {"string0", "string1", "string2"};
anArrayOfStrings[0]; //the first element
System.out.println(anArrayOfStrings[1]); //print the second element
anArrayOfStrings[2] = "new string value"; //assign the third element to a new value
if (anArrayOfStrings[0].equals("string0") //evaluate the first element and call a method
{
//this block will execute anArrayOfStrings[0] is "string0"
}
anArrayOfStrings[3]; //error, index out of bounds
Simply declaring the array would be
String[] names;
In your code you both declare and assign it in the same line by using an initializer list.
To assign individual elements, use the [] notation. Note that once you initialized you list to be only one String long, it cannot become longer than without be re-assigned. To declare an array of any size, you can use:
String[] arrayWithInitialSize = new String[5]; //holds five strings, each null to begin with

Categories