How to write String Iteration with Map Put operations in Java 8? - string

I am trying to convert following code into Java 8::
String s = "12345";
Map<Character,Integer> map = new HashMap<Character,Integer>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (map.containsKey(c)) {
int cnt = map.get(c);
map.put(c, ++cnt);
} else {
map.put(c, 1);
}
}
I tried and found following way to iterate:
IntStream.rangeClosed(0, s.length).foreach(d -> {
//all statements from char to map.put
}) ;
I am not sure whether this is correct way to do it.

You can do this:
s.chars()
.mapToObj(x -> (char) x)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
.mapToObj(x -> (char) x) is necessary because .chars() gives you a stream of ints, but in order to use groupingBy you need to work with objects, not primitives
groupingBy receives a function to get the key to group by and a Collector implementation
Function.identity() is just a function that returns whatever element it is passed to it
Collectors.counting() is a collector that counts

You can use the groupingBy() and counting() collectors:
String s = "12345";
Map<Character, Long> map = s
.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(map);
Unfortunately, there seems to be no convenient way to get a Stream<Character> from a string, hence the need to map to an IntStream using chars() and then using mapToObj() to convert it to a character stream.

Related

Program to find if a string is a palindrome keeps on failing. Even after using toLowerCase() command for both strings, output doesn't come

import java.util.Scanner;
class Palindrome_string
{
public static void main()
{
System.out.println("\f");
Scanner sc = new Scanner(System.in);
System.out.println("Enter a string");
String a = sc.nextLine();
int b = a.length();
String rev = "";
for (int i = b - 1; i >= 0; i--)
{
char c = a.charAt(i);
rev = rev + c;
}
System.out.println("Original word "+a);
System.out.println("Reversed word "+rev);
a = a.toLowerCase();
rev = rev.toLowerCase();
if (a == rev)
{
System.out.println("It is a palindrome");
}
else
{
System.out.println("It is not a palindrome");
}
sc.close();
}
}
The program compiles properly. Still, when running the program, the message which tells if it is a palindrome prints incorrectly. What changes do I make? Here is a picture of the output. Even though the word 'level' (which is a palindrome) has been inputted, it shows that it isn't a palindrome. What changes should I make? output pic
You should not use == to compare two strings because it compares the reference of the string, i.e. whether they are the same object or not.
Use .equals() instead. It tests for value equality. So in your case:
if (a.equals(rev))
{
System.out.println("It is a palindrome");
}
Also try not to use single-letter variable names except for index variables when iterating over a list etc. It's bad practice.

Convert string to double without parse or tryparse in C#

How can I convert a string to a double using a method that does not include parse or tryparse? I have the program for converting a string to a long, would it be the same for a double? I am a complete newbie.
Code snippets from OP comment below:
public static bool isLong(string s) {
bool n = true;
int a = 0;
s = s.Trim();
for (a = 0; (a < s.Length); a = a + 1) {
n = n && ((s[a] >= '0') && (s[a] <= '9'));
}
return (n);
}
public static long toLong(string s) {
long ret = 0;
int a;
s = s.Trim();
if (isLong(s)) {
for (a = 0; (a< s.Length); a = a + 1) {
ret = (ret * 10) + (s[i] - '0');
}
} else {
}
return (ret);
}
I think I now understand the question. If so, the answer is yes, sort of.
long is an integer type, so processing one digit at a time is fairly straight forward.
double is a floating decimal type, so you have to figure out a way to deal with the decimal period in the middle.
Is this a class assignment or something where you absolutely must write this code on your own? If not, please consider using the library functions that already exist for this purpose, such as stod: http://www.cplusplus.com/reference/string/stod/

How to collect a string to a stack of characters in Java 8? [duplicate]

I would like to convert the string containing abc to a list of characters and a hashset of characters. How can I do that in Java ?
List<Character> charList = new ArrayList<Character>("abc".toCharArray());
In Java8 you can use streams I suppose.
List of Character objects:
List<Character> chars = str.chars()
.mapToObj(e->(char)e).collect(Collectors.toList());
And set could be obtained in a similar way:
Set<Character> charsSet = str.chars()
.mapToObj(e->(char)e).collect(Collectors.toSet());
You will have to either use a loop, or create a collection wrapper like Arrays.asList which works on primitive char arrays (or directly on strings).
List<Character> list = new ArrayList<Character>();
Set<Character> unique = new HashSet<Character>();
for(char c : "abc".toCharArray()) {
list.add(c);
unique.add(c);
}
Here is an Arrays.asList like wrapper for strings:
public List<Character> asList(final String string) {
return new AbstractList<Character>() {
public int size() { return string.length(); }
public Character get(int index) { return string.charAt(index); }
};
}
This one is an immutable list, though. If you want a mutable list, use this with a char[]:
public List<Character> asList(final char[] string) {
return new AbstractList<Character>() {
public int size() { return string.length; }
public Character get(int index) { return string[index]; }
public Character set(int index, Character newVal) {
char old = string[index];
string[index] = newVal;
return old;
}
};
}
Analogous to this you can implement this for the other primitive types.
Note that using this normally is not recommended, since for every access you
would do a boxing and unboxing operation.
The Guava library contains similar List wrapper methods for several primitive array classes, like Chars.asList, and a wrapper for String in Lists.charactersOf(String).
The lack of a good way to convert between a primitive array and a collection of its corresponding wrapper type is solved by some third party libraries. Guava, a very common one, has a convenience method to do the conversion:
List<Character> characterList = Chars.asList("abc".toCharArray());
Set<Character> characterSet = new HashSet<Character>(characterList);
Use a Java 8 Stream.
myString.chars().mapToObj(i -> (char) i).collect(Collectors.toList());
Breakdown:
myString
.chars() // Convert to an IntStream
.mapToObj(i -> (char) i) // Convert int to char, which gets boxed to Character
.collect(Collectors.toList()); // Collect in a List<Character>
(I have absolutely no idea why String#chars() returns an IntStream.)
The most straightforward way is to use a for loop to add elements to a new List:
String abc = "abc";
List<Character> charList = new ArrayList<Character>();
for (char c : abc.toCharArray()) {
charList.add(c);
}
Similarly, for a Set:
String abc = "abc";
Set<Character> charSet = new HashSet<Character>();
for (char c : abc.toCharArray()) {
charSet.add(c);
}
List<String> result = Arrays.asList("abc".split(""));
Create an empty list of Character and then make a loop to get every character from the array and put them in the list one by one.
List<Character> characterList = new ArrayList<Character>();
char arrayChar[] = abc.toCharArray();
for (char aChar : arrayChar)
{
characterList.add(aChar); // autoboxing
}
You can do this without boxing if you use Eclipse Collections:
CharAdapter abc = Strings.asChars("abc");
CharList list = abc.toList();
CharSet set = abc.toSet();
CharBag bag = abc.toBag();
Because CharAdapter is an ImmutableCharList, calling collect on it will return an ImmutableList.
ImmutableList<Character> immutableList = abc.collect(Character::valueOf);
If you want to return a boxed List, Set or Bag of Character, the following will work:
LazyIterable<Character> lazyIterable = abc.asLazy().collect(Character::valueOf);
List<Character> list = lazyIterable.toList();
Set<Character> set = lazyIterable.toSet();
Bag<Character> set = lazyIterable.toBag();
Note: I am a committer for Eclipse Collections.
IntStream can be used to access each character and add them to the list.
String str = "abc";
List<Character> charList = new ArrayList<>();
IntStream.range(0,str.length()).forEach(i -> charList.add(str.charAt(i)));
Using Java 8 - Stream Funtion:
Converting A String into Character List:
ArrayList<Character> characterList = givenStringVariable
.chars()
.mapToObj(c-> (char)c)
.collect(collectors.toList());
Converting A Character List into String:
String givenStringVariable = characterList
.stream()
.map(String::valueOf)
.collect(Collectors.joining())
To get a list of Characters / Strings -
List<String> stringsOfCharacters = string.chars().
mapToObj(i -> (char)i).
map(c -> c.toString()).
collect(Collectors.toList());

Dynamic character generator; Generate all possible strings from a character set

I want to make a dynamic string generator that will generate all possible unique strings from a character set with a dynamic length.
I can make this very easily using for loops but then its static and not dynamic length.
// Prints all possible strings with the length of 3
for a in allowedCharacters {
for b in allowedCharacters {
for c in allowedCharacters {
println(a+b+c)
}
}
}
But when I want to make this dynamic of length so I can just call generate(length: 5) I get confused.
I found this Stackoverflow question But the accepted answer generates strings 1-maxLength length and I want maxLength on ever string.
As noted above, use recursion. Here is how it can be done with C#:
static IEnumerable<string> Generate(int length, char[] allowed_chars)
{
if (length == 1)
{
foreach (char c in allowed_chars)
yield return c.ToString();
}
else
{
var sub_strings = Generate(length - 1, allowed_chars);
foreach (char c in allowed_chars)
{
foreach (string sub in sub_strings)
{
yield return c + sub;
}
}
}
}
private static void Main(string[] args)
{
string chars = "abc";
List<string> result = Generate(3, chars.ToCharArray()).ToList();
}
Please note that the run time of this algorithm and the amount of data it returns is exponential as the length increases which means that if you have large lengths, you should expect the code to take a long time and to return a huge amount of data.
Translation of #YacoubMassad's C# code to Swift:
func generate(length: Int, allowedChars: [String]) -> [String] {
if length == 1 {
return allowedChars
}
else {
let subStrings = generate(length - 1, allowedChars: allowedChars)
var arr = [String]()
for c in allowedChars {
for sub in subStrings {
arr.append(c + sub)
}
}
return arr
}
}
println(generate(3, allowedChars: ["a", "b", "c"]))
Prints:
aaa, aab, aac, aba, abb, abc, aca, acb, acc, baa, bab, bac, bba, bbb, bbc, bca, bcb, bcc, caa, cab, cac, cba, cbb, cbc, cca, ccb, ccc
While you can (obviously enough) use recursion to solve this problem, it quite an inefficient way to do the job.
What you're really doing is just counting. In your example, with "a", "b" and "c" as the allowed characters, you're counting in base 3, and since you're allowing three character strings, they're three digit numbers.
An N-digit number in base M can represent NM different possible values, going from 0 through NM-1. So, for your case, that's limit=pow(3, 3)-1;. To generate all those values, you just count from 0 through the limit, and convert each number to base M, using the specified characters as the "digits". For example, in C++ the code can look like this:
#include <string>
#include <iostream>
int main() {
std::string letters = "abc";
std::size_t base = letters.length();
std::size_t digits = 3;
int limit = pow(base, digits);
for (int i = 0; i < limit; i++) {
int in = i;
for (int j = 0; j < digits; j++) {
std::cout << letters[in%base];
in /= base;
}
std::cout << "\t";
}
}
One minor note: as I've written it here, this produces the output in basically a little-endian format. That is, the "digit" that varies the fastest is on the left, and the one that changes the slowest is on the right.

Swift fast low level String lastIndexOf

I need an implementation of lastIndexOf that is as fast as possible.
I am finding that the String advance function is extremely slow.
I tried using the c function strrchr, and tried copying the string to NSData and using pointers but I can't get the syntax right.
My string will always have 1 byte characters and the string i'm searching for "|" is always 1 byte also.
Any implementation using advance will be too slow but here is the fastest example I could find:
func indexOf(target: String, startIndex: Int) -> Int
{
var startRange = advance(self.startIndex, startIndex)
var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
func lastIndexOf(target: String) -> Int
{
var index = -1
var stepIndex = self.indexOf(target)
while stepIndex > -1
{
index = stepIndex
if stepIndex + target.length < self.length
{
stepIndex = indexOf(target, startIndex: stepIndex + target.length)
}
else
{
stepIndex = -1
}
}
return index
}
This is an example of the string I need to parse.
var str:String = "4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4sageReceived:4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4TCPListener.onReceived: 4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|6|0|3259744|6352141|46|14|1|0|7|7|3259744|6352141|4|1|0|8|8|3259744|6352141|4|0|22|9|0|3259744|6352141|2|3|Room1|2|72|86330534|1|0|10|9|3259744|6352141|4|1|0|11|10|3259744|6352141|4|1|0|12|11|3259744|6352141|4|1|0|13|12|3259744|6352141|4|0|4|14|0|3259744|6352141|46|24|0|5|15|0|3259744|6352141|46|654|0|66|0|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.2212834|0|4|16|0|3259744|6352141|46|4preParse
4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|Mc02|efland,nc|36.027992|-79.221283"
Here is a Swift 2.0 Answer
func lastIndexOf(s: String) -> Int? {
if let r: Range<Index> = self.rangeOfString(s, options: .BackwardsSearch) {
return self.startIndex.distanceTo(r.startIndex)
}
return Optional<Int>()
}
Tests
func testStringLastIndexOf() {
let lastIndex = "0|2|45|7|9".lastIndexOf("|")
XCTAssertEqual(lastIndex, 8)
}
func testStringLastIndexOfNotFound() {
let lastIndex = "0123456789".lastIndexOf("|")
XCTAssertEqual(lastIndex, nil);
}
You can use strrchr in Swift
import Darwin
let str = "4|0|66|5|0|3259744|6352141|1|3259744"
func stringLastIndexOf(src:String, target:UnicodeScalar) -> Int? {
let c = Int32(bitPattern: target.value)
return src.withCString { s -> Int? in
let pos = strrchr(s, c)
return pos != nil ? pos - s : nil
}
}
stringLastIndexOf(str, "|") // -> {Some 28}
stringLastIndexOf(str, ",") // -> nil
You can use Objective C files in a Swift project; in these you can use plain C code and make a function which uses strrchr. Then you can call this from Swift.
If you do this in order to get all substring delimited by "|", you might test this approach:
import Foundation
let s = "4|0|66|5|0|3259744|6352141|1|3259744|WSMxt208L54yZ5irtHC3|..."
let a = s.componentsSeparatedByString("|")
The built in functions are sometimes very fast and you may be getting the required performance even by using String.
If you really need to get only the position of the last "|", you could work with utf16 representation, where advancing over the characters should be faster.
I think this should work:
let utf16String = s.utf16
var i = s.utf16Count - 1
while i >= 0 {
if utf16String[i] == 124 {
break
}
i--
}
println(i)
If the characters are guaranteed as single byte, the data is huge and performance is critical then it may be worth converting to an array of bytes (UInt8) and perform the operations directly on them. You can then convert the part that you need back to a String.
Also note that Optimised builds may be much faster than Debug builds so you should do any performance testing with the optimiser on. It may also be worth checking that the optimised versions are too slow at the moment.

Resources