Can anyone help me and tell how to convert a char array to a list and vice versa.
I am trying to write a program in which users enters a string (e.g "Mike is good") and in the output, each whitespace is replaced by "%20" (I.e "Mike%20is%20good"). Although this can be done in many ways but since insertion and deletion take O(1) time in linked list I thought of trying it with a linked list. I am looking for someway of converting a char array to a list, updating the list and then converting it back.
public class apples
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
StringBuffer sb = new StringBuffer(input.nextLine());
String s = sb.toString();
char[] c = s.toCharArray();
//LinkedList<char> l = new LinkedList<char>(Arrays.asList(c));
/* giving error "Syntax error on token " char",
Dimensions expected after this token"*/
}
}
So in this program the user is entering the string, which I am storing in a StringBuffer, which I am first converting to a string and then to a char array, but I am not able to get a list l from s.
I would be very grateful if someone can please tell the correct way to convert char array to a list and also vice versa.
In Java 8 and above, you can use the String's method chars():
myString.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
And if you need to convert char[] to List<Character>, you might create a String from it first and then apply the above solution. Though it won't be very readable and pretty, it will be quite short.
Because char is primitive type, standard Arrays.asList(char[]) won't work. It will produce List<char[]> in place of List<Character> ... so what's left is to iterate over array, and fill new list with the data from that array:
public static void main(String[] args) {
String s = "asdasdasda";
char[] chars = s.toCharArray();
// List<Character> list = Arrays.asList(chars); // this does not compile,
List<char[]> asList = Arrays.asList(chars); // because this DOES compile.
List<Character> listC = new ArrayList<Character>();
for (char c : chars) {
listC.add(c);
}
}
And this is how you convert List back to array:
Character[] array = listC.toArray(new Character[listC.size()]);
Funny thing is why List<char[]> asList = Arrays.asList(chars); does what it does: asList can take array or vararg. In this case char [] chars is considered as single valued vararg of char[]! So you can also write something like
List<char[]> asList = Arrays.asList(chars, new char[1]); :)
Another way than using a loop would be to use Guava's Chars.asList() method. Then the code to convert a String to a LinkedList of Character is just:
LinkedList<Character> characterList = new LinkedList<Character>(Chars.asList(string.toCharArray()));
or, in a more Guava way:
LinkedList<Character> characterList = Lists.newLinkedList(Chars.asList(string.toCharArray()));
The Guava library contains a lot of good stuff, so it's worth including it in your project.
Now I will post this answer as a another option for all those developers that are not allowed to use any lib but ONLY the Power of java 8:)
char[] myCharArray = { 'H', 'e', 'l', 'l', 'o', '-', 'X', 'o', 'c', 'e' };
Stream<Character> myStreamOfCharacters = IntStream
.range(0, myCharArray.length)
.mapToObj(i -> myCharArray[i]);
List<Character> myListOfCharacters = myStreamOfCharacters.collect(Collectors.toList());
myListOfCharacters.forEach(System.out::println);
You cannot use generics in java with primitive types, why?
If you really want to convert to List and back to array then dantuch's approach is the correct one.
But if you just want to do the replacement there are methods out there (namely java.lang.String's replaceAll) that can do it for you
private static String replaceWhitespaces(String string, String replacement) {
return string != null ? string.replaceAll("\\s", replacement) : null;
}
You can use it like this:
StringBuffer s = new StringBuffer("Mike is good");
System.out.println(replaceWhitespaces(s.toString(), "%20"));
Output:
Mike%20is%20good
All Operations can be done in java 8 or above:
To the Character array from a Given String
char[] characterArray = myString.toCharArray();
To get the Character List from given String
ArrayList<Character> characterList
= (ArrayList<Character>) myString.chars().mapToObj(c -> (char)c).collect(Collectors.toList());
To get the characters set from given String
Note: sets only stores unique value. so if you want to get only unique characters from a string, this can be used.
HashSet<Character> abc =
(HashSet<Character>) given.chars().mapToObj(c -> (char)c).collect(Collectors.toSet());
To get Characters in a specific range from given String :
To get the character whose unicode value is greater than 118.
https://unicode-table.com/en/#basic-latin
ASCII Code value for characters
* a-z - 97 - 122
* A-Z - 65 - 90
given.chars().filter(a -> a > 118).mapToObj(c -> (char)c).forEach(a -> System.out.println(a));
It will return the characters: w,x, v, z
you ascii values in the filter you can play with characters. you can do operations on character in filter and then you can collect them in list or set as per you need
I guess the simplest way to do this would be by simply iterating over the char array and adding each element to the ArrayList of Characters, in the following manner:
public ArrayList<Character> wordToList () {
char[] brokenStr = "testing".toCharArray();
ArrayList<Character> result = new ArrayList<Character>();
for (char ch : brokenStr) {
result.add(ch);
}
return result;
}
List strList = Stream.of( s.toCharArray() ).map( String::valueOf ).collect( Collectors.toList() );
Try Java Streams.
List<Character> list = s.chars().mapToObj( c -> (char)c).collect(Collectors.toList());
Generic arguments cannot be primitive type.
if you really want to convert char[] to List, you can use .chars() to make your string turns into IntStream, but you need to convert your char[] into String first
List<Character> charlist = String.copyValueOf(arrChr)
.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.toList());
Try this solution
List<Character> characterList = String.valueOf(chars).chars().mapToObj(i -> (char) i).toList();
Related
I have a weird situation, am working on a Data base project that only gives me a string [] s = ["A","B","C","D"] and I wanted to change from string array to Char Array since it's a char but i dunno what function to use to convert the entire array to char with one line of code.
char ch = [ 'A', 'B', 'C'] --> this is what am looking to get
My plan B is to loop the entire string and convert to char one by one. but am avoiding that one.
any help I will highly appreciate
this might help you.
Would be better if we could use Stream<char>, but, this does not work, so, we need to use the wrapper class.
Since you want the first index, you can use 0.
String.charAt(index) returns a char primitive, so, it will use less memory than a String.substring(...) that returns a new String.
final String[] array = {"A", "B", "C", "D"};
final Character [] char_array = Arrays.stream(array)
.map(s -> s.charAt(0))
.toArray(Character[]::new);
for(char a: char_array) {
System.out.println(a);
}
You can use streams, this will return a char [] array.
Arrays.stream(S).map(s -> s.substring(0,1)).collect(Collectors.joining()).toCharArray();
Full code
String [] S = { "A", "B", "C"} ;
char [] ch =Arrays.stream(S).map(s -> s.substring(0,1))
.collect(Collectors.joining()).toCharArray();
for(int i=0;i<ch.length;i++){
System.out.println(ch[i]);
}
For better use, I suggest making a method that implements this stream and returns a char []
public char [] convertToChar(String [] yourArray){
return Arrays.stream(youArray).map(s -> s.substring(0,1)).collect(Collectors.joining()).toCharArray();
}
I'm trying to apply my knowledge of streams to some leetcode algorithm questions. Here is a general summary of the question:
Given a string which contains only lowercase letters, remove duplicate
letters so that every letter appears once and only once. You must make
sure your result is the smallest in lexicographical order among all
possible results.
Example:
Input: "bcabc"
Output: "abc"
Another example:
Input: "cbacdcbc"
Output: "acdb"
This seemed like a simple problem, just stream the values into a new list from the string, sort the values, find the distinct values, and then throw it back into a list, and append the list's value to a string. Here is what I came up with:
public String removeDuplicateLetters(String s)
{
char[] c = s.toCharArray();
List<Character> list = new ArrayList<>();
for(char ch : c)
{
list.add(ch);
}
List<Character> newVal = list.stream().distinct().collect(Collectors.toList());
String newStr = "";
for(char ch : newVal)
{
newStr += ch;
}
return newStr;
}
The first example is working perfectly, but instead of "acdb" for the second output, I'm getting "abcd". Why would abcd not be the least lexicographical order? Thanks!
As I had pointed out in the comments using a LinkedHashSet would be best here, but for the Streams practice you could do this:
public static String removeDuplicateLetters(String s) {
return s.chars().sorted().distinct().collect(
StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append
).toString();
}
Note: distinct() comes after sorted() in order to optimize the stream, see Holger's explanation in the comments as well as this answer.
Lot of different things here so I'll number them:
You can stream the characters of a String using String#chars() instead of making a List where you add all the characters.
To ensure that the resulting string is smallest in lexographical order, we can sort the IntStream.
We can convert the IntStream back to a String by performing a mutable reduction with a StringBuilder. We then convert this StringBuilder to our desired string.
A mutable reduction is the Stream way of doing the equivalent of something like:
for (char ch : newVal) {
newStr += ch;
}
However, this has the added benefit of using a StringBuilder for concatenation instead of a String. See this answer as to why this is more performant.
For the actual question you have about the conflict of expected vs. observed output: I believe abcd is the right answer for the second output, since it is the smallest in lexographical order.
public static void main(String[] args) {
String string = "cbacdcbc";
string.chars()
.mapToObj(item -> (char) item)
.collect(Collectors.toSet()).forEach(System.out::print);
}
the output:abcd,hope help you!
private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
SortedSet<Character> set= new TreeSet<Character>();
for (int i = 0; i < ALPHABET.length(); i++) {
set.add(new Character(ALPHABET.charAt(i)));
}
I would like to convert this for loop in Java 8 way. It could be better if using a stream. Output will be the "set" object with contains the Character.
String has a method which will give you a stream of characters. It's actually an IntStream so we just need to convert them to Characters and then collect to a set.
"foo".chars()
.mapToObj(chr -> (char) chr) // autoboxed to Character
.collect(Collectors.toSet());
or use TreeSet::new as others have shown if you need the set to be sorted.
IntStream.range(0, ALPHABET.length())
.mapToObj(ALPHABET::charAt)
.collect(Collectors.toCollection(TreeSet::new));
I think this is the simplest way, preserving the requirement of using a TreeSet. Notice that there's no need to iterate over the input string using indexes, you can directly iterate over its characters.
SortedSet<Character> set =
ALPHABET.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.toCollection(TreeSet::new));
I need to split a String into an array of single character Strings.
Eg, splitting "cat" would give the array "c", "a", "t"
"cat".split("(?!^)")
This will produce
array ["c", "a", "t"]
"cat".toCharArray()
But if you need strings
"cat".split("")
Edit: which will return an empty first value.
String str = "cat";
char[] cArray = str.toCharArray();
If characters beyond Basic Multilingual Plane are expected on input (some CJK characters, new emoji...), approaches such as "a💫b".split("(?!^)") cannot be used, because they break such characters (results into array ["a", "?", "?", "b"]) and something safer has to be used:
"a💫b".codePoints()
.mapToObj(cp -> new String(Character.toChars(cp)))
.toArray(size -> new String[size]);
split("(?!^)") does not work correctly if the string contains surrogate pairs. You should use split("(?<=.)").
String[] splitted = "花ab🌹🌺🌷".split("(?<=.)");
System.out.println(Arrays.toString(splitted));
output:
[花, a, b, 🌹, 🌺, 🌷]
To sum up the other answers...
This works on all Java versions:
"cat".split("(?!^)")
This only works on Java 8 and up:
"cat".split("")
An efficient way of turning a String into an array of one-character Strings would be to do this:
String[] res = new String[str.length()];
for (int i = 0; i < str.length(); i++) {
res[i] = Character.toString(str.charAt(i));
}
However, this does not take account of the fact that a char in a String could actually represent half of a Unicode code-point. (If the code-point is not in the BMP.) To deal with that you need to iterate through the code points ... which is more complicated.
This approach will be faster than using String.split(/* clever regex*/), and it will probably be faster than using Java 8+ streams. It is probable faster than this:
String[] res = new String[str.length()];
int 0 = 0;
for (char ch: str.toCharArray[]) {
res[i++] = Character.toString(ch);
}
because toCharArray has to copy the characters to a new array.
for(int i=0;i<str.length();i++)
{
System.out.println(str.charAt(i));
}
Maybe you can use a for loop that goes through the String content and extract characters by characters using the charAt method.
Combined with an ArrayList<String> for example you can get your array of individual characters.
If the original string contains supplementary Unicode characters, then split() would not work, as it splits these characters into surrogate pairs. To correctly handle these special characters, a code like this works:
String[] chars = new String[stringToSplit.codePointCount(0, stringToSplit.length())];
for (int i = 0, j = 0; i < stringToSplit.length(); j++) {
int cp = stringToSplit.codePointAt(i);
char c[] = Character.toChars(cp);
chars[j] = new String(c);
i += Character.charCount(cp);
}
In my previous answer I mixed up with JavaScript. Here goes an analysis of performance in Java.
I agree with the need for attention on the Unicode Surrogate Pairs in Java String. This breaks the meaning of methods like String.length() or even the functional meaning of Character because it's ultimately a technical object which may not represent one character in human language.
I implemented 4 methods that split a string into list of character-representing strings (Strings corresponding to human meaning of characters). And here's the result of comparison:
A line is a String consisting of 1000 arbitrary chosen emojis and 1000 ASCII characters (1000 times <emoji><ascii>, total 2000 "characters" in human meaning).
(discarding 256 and 512 measures)
Implementations:
codePoints (java 11 and above)
public static List<String> toCharacterStringListWithCodePoints(String str) {
if (str == null) {
return Collections.emptyList();
}
return str.codePoints()
.mapToObj(Character::toString)
.collect(Collectors.toList());
}
classic
public static List<String> toCharacterStringListWithIfBlock(String str) {
if (str == null) {
return Collections.emptyList();
}
List<String> strings = new ArrayList<>();
char[] charArray = str.toCharArray();
int delta = 1;
for (int i = 0; i < charArray.length; i += delta) {
delta = 1;
if (i < charArray.length - 1 && Character.isSurrogatePair(charArray[i], charArray[i + 1])) {
delta = 2;
strings.add(String.valueOf(new char[]{ charArray[i], charArray[i + 1] }));
} else {
strings.add(Character.toString(charArray[i]));
}
}
return strings;
}
regex
static final Pattern p = Pattern.compile("(?<=.)");
public static List<String> toCharacterStringListWithRegex(String str) {
if (str == null) {
return Collections.emptyList();
}
return Arrays.asList(p.split(str));
}
Annex (RAW DATA):
codePoints;classic;regex;lines
45;44;84;256
14;20;98;512
29;42;91;1024
52;56;99;2048
87;121;174;4096
175;221;375;8192
345;411;839;16384
667;826;1285;32768
1277;1536;2440;65536
2426;2938;4238;131072
We can do this simply by
const string = 'hello';
console.log([...string]); // -> ['h','e','l','l','o']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax says
Spread syntax (...) allows an iterable such as an array expression or string to be expanded...
So, strings can be quite simply spread into arrays of characters.
e.g.:
If the number is 234, I would like the result to be List<String> containing 2,3,4 (3 elements)
If the number is 8763, I would like the result to be List<String> containing 8,7,6,3 (4 elements)
Does commons-math already have such a function?
Convert the number to a String (123 becomes "123"). Use Integer.toString.
Convert the string to a char array ("123" becomes {'1', '2', '3'}). Use String.toCharArray.
Construct a new, empty Vector<String> (or some other List type).
Convert each char in the char array to a String and push it onto the Vector ({'1', '2', '3'} becomes a Vector with "1", "2" and "3"). Use a for loop, Character.toString and List.add.
Edit: You can't use the Vector constructor; have to do it manually.
int num = 123;
char[] chars = Integer.toString(num).toCharArray();
List<String> parts = new Vector<String>();
for (char c : chars)
{
parts.add(Character.toString(c));
}
There isn't an easier way to do this because it really isn't a very obvious or common thing to want to do. For one thing, why do you need a List of Strings? Can you just have a list of Characters? That would eliminate step 3. Secondly, does it have to be a List or can it just be an array? That would eliminate step 4.
You can use the built in java.util.Arrays.asList:
int num = 234;
List<String> parts = Arrays.asList(String.valueOf(num).split("\\B"));
Step by step this:
Converts num to a String using String.valueOf(num)
Splits the String by non-word boundaries, in this case, every letter boundary except the start and the finish, using .split("\\B") (this returns a String[])
Converts the String[] to a List<String> using Arrays.asList(T...)
Arrays.asList( String.valueOf(number).toCharArray() )
Try this:
Arrays.asList(String.valueOf(1234).split("(?!^)"))
It will create list of Strings:
["1", "2", "3", "4"]
This seems like homework.
Consider using % and / to get each digit instead of converting the entire number to a String