Related
I am struggling with removing spaces in an arraylist of strings.
Say the user input is as follows: "I walked my dog", my code outputs this:
[I, walked, my, dog]
I want it to have no spaces as such:
[I,walked,my,dog]
I tried to remove whitespace on each individual string before I add it to the arrayList, but the output still has the spaces.
Scanner input = new Scanner(System.in);
ArrayList<String> userWords = new ArrayList<String>();
ArrayList<String> SplituserWords = new ArrayList<String>();
System.out.println("Please enter your phrase: ");
userWords.add(input.nextLine());
for (int index = 0; index < userWords.size(); index++) {
String[] split = userWords.get(index).split("\\s+");
for (String word : split) {
word.replaceAll("\\s+","");
SplituserWords.add(word);
}
System.out.println(SplituserWords);
I suggest just taking advantage of the built-in Arrays#toString() method here:
String words = input.nextLine();
String output = Arrays.toString(words.split(" ")).replace(" ", "");
System.out.println(output); // [I,walked,my,dog]
When you are writing System.out.println(SplituserWords);, you are implicitly calling ArrayList#toString() which generates the list's string and that includes spaces after commas.
You can instead generates your own string output, for example with:
System.out.println("[" + String.join(",", SplituserWords) + "]");
If you insist on using List, it will do it for you.
String input = "I walked my dog";
List<String> SplitUserWords = Arrays.asList(input.split(" "));
String output = SplitUserWords.toString().replace(" ", "");
System.out.println(output); //[I,walked,my,dog]
I tried to remove whitespace on each individual string before I add it to the arrayList, but the output still has the spaces.
That won't work because that isn't the problem. The issue is that it is the list implementation that formats the output for you inserts a space after each comma. It does this in the toString() method. To avoid having to explicitly call replace each time you can also do it like this by overidding toString() when you create your List.
List<String> myList = new ArrayList<>(List.of("I","walked","my", "dog")) {
#Override
public String toString() {
// use super to call the overidden method to format the string
// then remove the spaces and return the new String
return super.toString().replace(" ", "");
}
};
System.out.println(myList);
myList.addAll(List.of("and", "then","fed", "my", "cat"));
System.out.println(myList);
prints
[I,walked,my,dog]
[I,walked,my,dog,and,then,fed,my,cat]
You can also subclass ArrayList as follows. Here I have added the three constructors that ArrayList implements. Note that is is a somewhat extreme solution and may not be worth it for occasionally reformatting of the output. I included it for your consideration.
class MyArrayList<E> extends ArrayList<E> {
public MyArrayList() {
super();
}
public MyArrayList(int capacity) {
super(capacity);
}
public MyArrayList(Collection<? extends E> c) {
super(c);
}
#Override
public String toString() {
return super.toString().replace(" ", "");
}
}
And it would work like so.
MyArrayList<String> myList = new MyArrayList<>(List.of("This", "is", "a","test."));
System.out.println(myList);
prints
[This,is,a,test.]
I want the Java code for converting an array of strings into an string.
Java 8+
Use String.join():
String str = String.join(",", arr);
Note that arr can also be any Iterable (such as a list), not just an array.
If you have a Stream, you can use the joining collector:
Stream.of("a", "b", "c")
.collect(Collectors.joining(","))
Legacy (Java 7 and earlier)
StringBuilder builder = new StringBuilder();
for(String s : arr) {
builder.append(s);
}
String str = builder.toString();
Alternatively, if you just want a "debug-style" dump of an array:
String str = Arrays.toString(arr);
Note that if you're really legacy (Java 1.4 and earlier) you'll need to replace StringBuilder there with StringBuffer.
Android
Use TextUtils.join():
String str = TextUtils.join(",", arr);
General notes
You can modify all the above examples depending on what characters, if any, you want in between strings.
DON'T use a string and just append to it with += in a loop like some of the answers show here. This sends the GC through the roof because you're creating and throwing away as many string objects as you have items in your array. For small arrays you might not really notice the difference, but for large ones it can be orders of magnitude slower.
Use Apache commons StringUtils.join(). It takes an array, as a parameter (and also has overloads for Iterable and Iterator parameters) and calls toString() on each element (if it is not null) to get each elements string representation. Each elements string representation is then joined into one string with a separator in between if one is specified:
String joinedString = StringUtils.join(new Object[]{"a", "b", 1}, "-");
System.out.println(joinedString);
Produces:
a-b-1
I like using Google's Guava Joiner for this, e.g.:
Joiner.on(", ").skipNulls().join("Harry", null, "Ron", "Hermione");
would produce the same String as:
new String("Harry, Ron, Hermione");
ETA: Java 8 has similar support now:
String.join(", ", "Harry", "Ron", "Hermione");
Can't see support for skipping null values, but that's easily worked around.
From Java 8, the simplest way I think is:
String[] array = { "cat", "mouse" };
String delimiter = "";
String result = String.join(delimiter, array);
This way you can choose an arbitrary delimiter.
You could do this, given an array a of primitive type:
StringBuffer result = new StringBuffer();
for (int i = 0; i < a.length; i++) {
result.append( a[i] );
//result.append( optional separator );
}
String mynewstring = result.toString();
Try the Arrays.deepToString method.
Returns a string representation of the "deep contents" of the specified
array. If the array contains other arrays as elements, the string
representation contains their contents and so on. This method is
designed for converting multidimensional arrays to strings
Try the Arrays.toString overloaded methods.
Or else, try this below generic implementation:
public static void main(String... args) throws Exception {
String[] array = {"ABC", "XYZ", "PQR"};
System.out.println(new Test().join(array, ", "));
}
public <T> String join(T[] array, String cement) {
StringBuilder builder = new StringBuilder();
if(array == null || array.length == 0) {
return null;
}
for (T t : array) {
builder.append(t).append(cement);
}
builder.delete(builder.length() - cement.length(), builder.length());
return builder.toString();
}
public class ArrayToString
{
public static void main(String[] args)
{
String[] strArray = new String[]{"Java", "PHP", ".NET", "PERL", "C", "COBOL"};
String newString = Arrays.toString(strArray);
newString = newString.substring(1, newString.length()-1);
System.out.println("New New String: " + newString);
}
}
You want code which produce string from arrayList,
Iterate through all elements in list and add it to your String result
you can do this in 2 ways: using String as result or StringBuffer/StringBuilder.
Example:
String result = "";
for (String s : list) {
result += s;
}
...but this isn't good practice because of performance reason. Better is using StringBuffer (threads safe) or StringBuilder which are more appropriate to adding Strings
String[] strings = new String[25000];
for (int i = 0; i < 25000; i++) strings[i] = '1234567';
String result;
result = "";
for (String s : strings) result += s;
//linear +: 5s
result = "";
for (String s : strings) result = result.concat(s);
//linear .concat: 2.5s
result = String.join("", strings);
//Java 8 .join: 3ms
Public String join(String delimiter, String[] s)
{
int ls = s.length;
switch (ls)
{
case 0: return "";
case 1: return s[0];
case 2: return s[0].concat(delimiter).concat(s[1]);
default:
int l1 = ls / 2;
String[] s1 = Arrays.copyOfRange(s, 0, l1);
String[] s2 = Arrays.copyOfRange(s, l1, ls);
return join(delimiter, s1).concat(delimiter).concat(join(delimiter, s2));
}
}
result = join("", strings);
// Divide&Conquer join: 7ms
If you don't have the choise but to use Java 6 or 7 then you should use Divide&Conquer join.
String array[]={"one","two"};
String s="";
for(int i=0;i<array.length;i++)
{
s=s+array[i];
}
System.out.print(s);
Use Apache Commons' StringUtils library's join method.
String[] stringArray = {"a","b","c"};
StringUtils.join(stringArray, ",");
When we use stream we do have more flexibility, like
map --> convert any array object to toString
filter --> remove when it is empty
join --> Adding joining character
//Deduplicate the comma character in the input string
String[] splits = input.split("\\s*,\\s*");
return Arrays.stream(splits).filter(StringUtils::isNotBlank).collect(Collectors.joining(", "));
If you know how much elements the array has, a simple way is doing this:
String appendedString = "" + array[0] + "" + array[1] + "" + array[2] + "" + array[3];
I have an ArrayList,where I search for needed element and then add the needed part of it to another ArrayList. The problem is that if I want to keep searching for the words,not only one word,I don't know how to keep going on the elements through the loop. With the using of iterator, I wouldn't be able to search for things I need.
public static ArrayList<String> FindWord(){
ArrayList<String> rewrite=new ArrayList<>();//
ArrayList<String> word=Reading();// rewrites the data from one string to other
String userinput=Chat();
for(String elmt:word){
if (elmt.contains(userinput) && elmt.contains("=")) {
String[] parts=elmt.split("\\=");
rewrite.add(parts[1]);
// here I must do something like word.next
}
}
System.out.println(rewrite);
return rewrite; // RETURNS THE SYNONIM OF THE WORD
}
So,it goes like if I input "hello", it will find me the word "greeting",which is a synonim in my text file. If I input "awesome", it will find the word "thanks", but if I input both of them it will input an empty array, like nothing is found instead of " greeting, thanks"
UPD:
The Reading() returns:
public static ArrayList<String> Reading() {
Scanner inputreader = null;
try {
inputreader = new Scanner(new FileInputStream("D:\\sinonims.txt"));
}catch (FileNotFoundException e1) { // OPENS FILE WITH SINONIMS
e1.printStackTrace();
System.out.println("File not found");
System.exit(0);
}
ArrayList<String> Sins=new ArrayList();
while(inputreader.hasNextLine()){
String l=inputreader.nextLine();
Sins.add(l); // REWRITES DATA FROM FILE TO ARRATLIST
}
inputreader.close();
System.out.print(Sins);
return Sins;
}
public static String Chat(){
System.out.println("Let's start talking.");
Scanner in=new Scanner(System.in);
String line=in.nextLine();
return line;
}
If you are trying to accept many inputs, you'll need to loop around the input & for loop.
The for loop already loops over all the words.
Note: I replaced contains for startsWith to prevent you catching the word on the other side of the equals
static ArrayList<String> word=Reading();
public static ArrayList<String> FindWord(){
ArrayList<String> rewrite=new ArrayList<>();
String userinput = "" ;
while (true) {
userinput=Chat();
if (userinput.equals("quit")) break;
for(String elmt:word){
if (elmt.startsWith(userinput) && elmt.contains("=")) {
String[] parts=elmt.split("\\=");
rewrite.add(parts[1]);
}
}
System.out.println(rewrite);
return rewrite; // RETURNS THE SYNONIM OF THE WORD
}
I can't really say this is the best way to approach your problem because it seems you need a Hashmap, not an Arraylist
contains fetches you exact match, split the text and match accordingly, store the results in new array list
you can create another arraylist and add your userinput values one by one into that list . you can iterate this newly created arraylist by using new for each loop on top of the current for each loop.
You should split the input string userinput with some specific delimiter.
Then for each word, Iterate through the splitted array and give each word as input , Find its Synonym with your technique and add it to the arraylist.
This can be implemented by doing some changes in your code.
public static ArrayList<String> FindWord()
{
ArrayList<String> rewrite=new ArrayList<>();
ArrayList<String> word=Reading();
String userinput=Chat();
String inputs[]=userinput.split(","); //Considering delimiter is comma(",") in user input
for(String input : inputs) //Giving each word as input at a time and search for it in word String
{
for(String elmt:word)
{
if (elmt.contains(input) && elmt.contains("="))
{
String[] parts=elmt.split("\\=");
rewrite.add(parts[1]);
}
}
}
System.out.println(rewrite);
return rewrite; // RETURNS THE SYNONIM OF THE WORD
}
So Here I am considering that the input is with delimiter Comma(",") so I have splitted input string with Comma(",") as you have given description in comments about your problem with space as delimiter.
When you will print the ArrayList, Automatically Output will be printed in separated manner with comma(, ).
So for Input : hello,awesome It will give output as greeting, thanks.
I try to parse a textfile which has lines which look like the following:
#KEY,_,0,1,2,_,4,5,6, ...
The #KEY is just an identifier in the beginning while the following numbers are my data which I want to store in an ArrayList<Integer>.
I have a metadata class which contains the arraylist in which I want to insert there integers:
class MetaD {
public List<Integer> key1, key2, key3 = new ArrayList<Integer>();
}
I parse the textfile line by line; when the line starts with #KEY, I want to add the elements to the key1 list. If there is an _, it should be replaced with an empty value:
if(line.startsWith("#KEY")){
metaObject.key1 = Arrays.asList(line.replace("#KEY,", "").replace("_", "").trim().split("\\s*,\\s*"));
}
I found out that this does not work with ArrayList<Integer>. key1 has to be of the type ArrayList<String> or ArrayList<Object> to make it work.
Is there a way to convert Integers in the same way?
If not, my idea would be the following:
Convert everything to an ArrayList<String>
Iterate every item of this new ArrayList and convert it with Integer.parseInt() into an Integer.
Adding this new Integer to my ArrayList<Integer>
Would there be a more efficient or better way to archive my needs?
Edit:
Since Tunaki wrote in the comments, that my idea will probably be the only possible way I tried to do the following:
if(line.startsWith("#KEY")){
List<String> channelTemp = Arrays.asList(line.replace("#KEY,", "").replace("_", "1").split("\\s*,\\s*"));
channelTemp.forEach(item -> metaObject.channel.add(Integer.parseInt(item)));
System.out.println("done");
}
Unfortunately, this throws a NullPointerException in the third line here and I don't have a clue why. I replaced _ with 1 for testing purposes to avoid a NumberFormatException. When I print out every object in the lambda function instead of adding them to my ArrayList<Integer>, I can see that all items have an Integer value. So why do I get an exception here?
Since you're almost there I'll give you a hand.
String line = "#KEY,_,0,1,2 , _,4,5,6,";
List<Integer> collect = Arrays.stream(line.replaceAll("#KEY|_", "").split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Integer::valueOf).collect(Collectors.toList());
System.out.println(collect);
EDIT
To obtain the null you can alter the mapping process like:
List<Integer> collect = Arrays.stream(line.split(","))
.skip(line.startsWith("#KEY") ? 1 : 0)
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(s -> "_".equals(s) ? null : Integer.valueOf(s)).collect(Collectors.toList());
You're trying to put in list of Integer a String:
metaObject.key1 = Arrays.asList(line.replace("#KEY,", "").replace("_", "").trim().split("\\s*,\\s*"));
Here line.replace(...) and trim() return a String, and split(...) returns a String[].
Therefore Arrays.asList(...) returns a List<String> here, that's not compatible with your definition of key1 (List<Integer>).
Yes, you can convert it to List<Integer> by call Integer.valueOf(...) or Integer.parseInt(...).
But I would recommend to
Use a new instance of List instead of Arrays.asList(...) because the latest one will produce an unmodifiable collection. Sometines it's not what you want :)
Use something less specific than your own text format. What about JSON? There are a lot of libraries to simplify parsing/storing of the data.
Firstly, you should split your string with ",", then you try if your each String is an integer or not with an isIntegerMethod. If it is an integer, you can add it into the list.
public static void main(String[] args) throws IOException {
String str = "#KEY,_,0,1,2,_,4,5,9";
String [] strArr = str.split(",");
List<Integer> intList = new ArrayList<Integer>();
for (String string : strArr) {
if (isInteger(string, 10)) {
intList.add(Integer.valueOf(string));
} else {
System.out.println(string + " is not an integer");
}
}
System.out.println(intList.toString());
}
public static boolean isInteger(String s, int radix) {
if(s.isEmpty()) return false;
for(int i = 0; i < s.length(); i++) {
if(i == 0 && s.charAt(i) == '-') {
if(s.length() == 1) return false;
else continue;
}
if(Character.digit(s.charAt(i),radix) < 0) return false;
}
return true;
}
Assuming there are no restrictions in the characters that can be used in the individual Strings, and the Strings may be empty.
Edit:
Seems like the proper way to do this is to use a separator, and to escape occurances of that separator that already exist in any of the individual strings. Below is my attempt to this, which seems to work. Did miss any cases that will break it?:
public static void main(String args[])
{
Vector<String> strings = new Vector<String>();
strings.add("abab;jmma");
strings.add("defgh;,;");
strings.add("d;;efgh;,;");
strings.add("");
strings.add("");
strings.add(";;");
strings.add(";,;");
String string = combine(strings);
strings= separate(string);
System.out.println();
}
static String combine(Vector<String> strings)
{
StringBuilder builder = new StringBuilder();
for(String string : strings)
{
//don't prepend a SEPARATOR to the first string
if(!builder.toString().equals(""))
{
builder.append(";");
}
string = string.replaceAll(";", ",;");
builder.append(string);
}
return builder.toString();
}
static Vector<String> separate(String string)
{
Vector<String> strings = new Vector<String>();
separate(string, strings, 0);
return strings;
}
static void separate(String string, Vector<String> strings, int currIndex)
{
int nextIndex = -1;
int checkIndex = currIndex;
while(nextIndex == -1 && checkIndex < string.length())
{
nextIndex = string.indexOf(';', checkIndex);
//look back to determine if this occurance is escaped
if(string.charAt(nextIndex - 1) == ',')
{
//this ones is escaped, doesn't count
checkIndex = nextIndex + 1;
nextIndex = -1;
}
}
if(nextIndex == -1)
{
//no more remain
String toAdd = string.substring(currIndex, string.length());
toAdd = toAdd.replaceAll(",;", ";");
strings.add(toAdd);
return;
}
else if(currIndex + 1 == nextIndex)
{
//empty string
strings.add("");
separate(string, strings, nextIndex);
}
else
{
//there could be more
String toAdd = string.substring(currIndex, nextIndex);
toAdd = toAdd.replaceAll(",;", ";");
strings.add(toAdd);
separate(string, strings, nextIndex + 1);
}
}
}
Take your Vector of Strings and convert it to a JSON object and store the JSON object.
( http://www.json.org/ and http://www.json.org/java/ )
With your code, you can recover empty strings using the two-argument version of split:
String[] separate(String string)
{
return string.split(SEPARATOR, -1);
}
If you can truly make no assumptions about the string contents, the only way to do this properly is by escaping the separator sequence (which can then be a single character) wherever it occurs in the source string(s). Obviously, if you escape the separator sequence, you need to unescape the result after splitting. (The escape mechanism will likely require additional at least one additional escape/unescape.)
EDIT
Here's an example (XML-inspired) of escaping and unescaping. It assumes that the separator sequence is "\u0000" (a single NULL character).
/** Returns a String guaranteed to have no NULL character. */
String escape(String source) {
return source.replace("&", "&").replace("\u0000", "&null;");
}
/** Reverses the above escaping and returns the result. */
String unescape(String escaped) {
return source.replace("&null;", "\u0000").replace("&", "&");
}
Many other variations are possible. (It is important that the replacements when unescaping are in reverse order from those used for escaping.) Note that you can still use String.split() to separate the components.
You can build a class that stores the individual strings internally and then outputs a concatenated version of the strings when you call toString. Getting the original strings back is trivial as you already have them stored individually.
You can have the same comportement in two lines of code using Google Guava library (Splitter and Joiner classes).
public String combine(Collection<String> strings) {
return Joiner.on("yourUniqueSeparator").join(strings);
}
public Iterable<String> separate(String toSeparate) {
return Splitter.on("yourUniqueSeparator").split(toSeparate);
}
Take a look at opencsv if you want to use delimited text. The api is rather easy to use, and it takes care of dealing with escaping quotes and the like. However, it treats null values as empty strings, so you might get a,,c if your input was { "a", null, "c" }. If that's not acceptable, you could use a recognizable string and convert it back later.
char tokenSeparator = ',';
char quoteChar = '"';
String inputData[] = {"a","b","c"};
StringWriter stringWriter = new StringWriter();
CSVWriter csvWriter = new CSVWriter(stringWriter, tokenSeparator, quoteChar);
csvWriter.writeNext(inputData);
csvWriter.close();
StringReader stringReader = new StringReader(stringWriter.toString());
CSVReader csvReader = new CSVReader(stringReader, tokenSeparator, quoteChar);
String outputData[] = csvReader.readNext();