I have a string in this format(response from EBS Payment Gateway)
key1=value1&key2=value2&key3=value3
How to bind to this class object without using split method?
public class MyClass {
private String key1;
private String key2;
private String key3;
// getter and setter methods
...
}
Try following
public class MyClass {
private String key1;
private String key2;
private String key2;
public MyClass(String k1,String k2,String k3)
{
Key1 = k1;
Key2 = k2;
Key3 = k3;
}
// getter and setter methods
...
}
And while creating object of class
String response = "key1=value1&key2=value2&key3=value3";
String[] keys = response.split("&");
MyClass m = new MyClass(keys[0].split("=")[1],keys[1].split("=")[1],keys[2].split("=")[1])
String template = "key1=value1&key2=value2&key3=value3";
String pattern = "&?([^&]+)=";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(template);
while (m.find())
{
System.out.println(m.group(1)); //prints capture group number 1
}
Output:
key1
key2
key3
Of course, this can be shortened to:
Matcher m = Pattern.compile("&?([^&]+)=").matcher("key1=value1&key2=value2&key3=value3");
while (m.find())
{
System.out.println(m.group(1)); //prints capture group number 1
}
Breakdown:
"&?([^&]+)=";
&?: says 0 or 1 &
[^&]+ matches 1 or more characters not equal to &
([^&]+) captures the above characters (allows you to extract them)
&?([^&]+)= captures the above characters such that they begin with 0 or 1 & and end with =
NB: Even though we did not exclude = in [^&], this expression works because if it could match anything with an = sign in it, that string would also have an '&' in it, so [^&=] is unnecessary.
Split your string into pieces and then set them using your setters.
String str = "key1=value1&key2=value2&key3=value3";
String[] split = str.split("&");
MyClass obj = new MyClass();
obj.setKey1(split[0].split("=")[1]);
obj.setKey2(split[1].split("=")[1]);
obj.setKey3(split[2].split("=")[1]);
The first split, splits the string at the & symbol.
key1=value1 [0]
key2=value2 [1]
key3=value [2]
After that, you split each of those on the = symbol
key1 [0][0]
value1 [0][1]
key2 [1][0]
value2 [1][1]
key3 [2][0]
value3 [2][1]
So as in the first code block, you have split[0].split("=")[1] which is [0][1] in the explanation below. That's value1
It's quick & dirty but it works perfectly fine :)
Try using beanutils and map
String[] keys = "key1=value1&key2=value2&key3=value3".split("&");
HashMap keyMap = new HashMap();
for(String key:keys){
String[] pair = key.split("=");
keyMap.put(pair[0],pair[1]);
}
MyClass myCls=new MyClass();
BeanUtils.populate(myCls,keyMap);
With Guava you can do this:
String str = "key1=value1&key2=value2&key3=value3";
Map<String, String> map = Splitter.on('&').withKeyValueSeparator("=").split(str);
and than you can do with the keys and values whatever you want. E.g.
mc.setKey1(map.get("key1")); // will set key1 to value1
This can be done by using the split element in java
Store your string in variable and call the split methord in java.
string = "key1=value1&key2=value2&key3=value3";
String[] keys = string.split("&");
IN the next step you can perform a split on each of the elements of the the array keys using the '=' character.
Ref : How to split a string in Java
You can use java reflection :
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyClass {
private String key1;
private String key2;
private String key3;
public void setKey1(String key1) {
this.key1 = key1;
}
public void setKey2(String key2) {
this.key2 = key2;
}
public void setKey3(String key3) {
this.key3 = key3;
}
public void setKey(String input) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
String[] strings = input.split("&");
String methodName = null;
Method setter = null;
for(String keyValue : strings) {
String[] keyValuePair = keyValue.split("=");
methodName = toSetterMethod(keyValuePair[0]);
setter = getMethod(methodName);
if (setter != null) {
setter.setAccessible(true);
setter.invoke(this, keyValuePair[1]);
}
}
}
private Method getMethod(String methodName) {
try {
Method[] methods = MyClass.class.getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method;
}
}
} catch (SecurityException e) {
}
return null;
}
private String toSetterMethod(String property) {
String setter = "set";
setter += property.substring(0, 1).toUpperCase() + property.substring(1);
return setter;
}
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
String input = "key1=value1&key2=value2&key3=value3";
MyClass myClass = new MyClass();
myClass.setKey(input);
System.out.println(myClass.key1);
System.out.println(myClass.key2);
System.out.println(myClass.key3);
}
}
Related
I have a TreeMap with 3 entries, all from individual ArrayLists.
I use the following code:
Map<String, List<String>> mapOne = new TreeMap<String, List<String>>();
List<String> listFour = Arrays.asList("");
ArrayList<String> listOne = new ArrayList<>();
listOne.add("Writer");
listOne.add("Actor");
listOne.add("Politician");
listOne.add("Dancer");
ArrayList<String> listTwo = new ArrayList<>();
listTwo.add("James");
listTwo.add("Robert");
listTwo.add("Tereza");
listTwo.add("John");
ArrayList<String> listThree = new ArrayList<>();
listThree.add("Joyce");
listThree.add("Redford");
listThree.add("May");
listThree.add("Travolta");
for (int i = 0; i < listOne.size(); i++) {
String stringOne = listOne.get(i);
String stringTwo = listTwo.get(i);
String stringThree = listThree.get(i);
listFour = Arrays.asList(stringTwo, stringThree);
mapOne.put(stringOne, listFour);
}
Now I want to obtain the individual String values from the sorted list. like so:
for (Map.Entry<String, List<String>> entry : mapOne.entrySet()) {
String key = entry.getKey();
for (String value : entry.getValue()) {
System.out.println(value);
}
}
The above code prints a list like
{Robert Redford , John Travolta , Tereza May , James Joyce}
Is it possible to iterate over the list in a way as to obtain to separate lists, one with the first names and the other with the last names?
listOne = {Robert , John , Tereza, James}
listTwo = {Redford, Travolta, May, Joyce}
Or should I use an entirely different approach?
The whole thing started out with the need to sort one ArrayList and to other accordingly. What seemed trivial at the beginning, turned out to be a real challenge.
I am a sort of a hobby programmer, so the pros out there kindly bear with me.
It seems you're over-engineering somehow.
I will answer with a Stream solution first, just for the sake of trying it.
Note that I'd, personally, prefer the "old" iterative approach (see below).
// You can see by the use of AtomicInteger that this isn't the right road to take!
final AtomicInteger i = new AtomicInteger();
final Collection<List<String>> values1 =
mapOne.values()
.stream()
.flatMap(v -> v.stream())
.collect(partitioningBy(o -> i.getAndIncrement() % 2 != 0))
.values();
Output: [[Robert, John, Tereza, James], [Redford, Travolta, May, Joyce]]
Iterative approach
final Collection<String> names = new ArrayList<>();
final Collection<String> surnames = new ArrayList<>();
for (final List<String> value : mapOne.values()) {
names.add(value.get(0));
surnames.add(value.get(1));
}
Output:
[Robert, John, Tereza, James]
[Redford, Travolta, May, Joyce]
This is safe because you know each inner List has two elements.
What JB Nizet is telling you to do (credit to him for writing that), is basically to create an appropriate class
public class Person {
private String profession;
private String name;
private String surname;
// Getters and setters. JavaBean style
}
And proceed to sort a Collection<Person>.
For example, keeping it as simple as possible
final List<Person> persons = new ArrayList<>();
// Populate list
Collections.sort(persons, (p1, p2) -> {
// Not null-safe
return p1.getName().compareTo(p2.getName());
});
This will sort the list by name. It will not return a new List, but simply modify the input one.
Putting all the valuable tips, online searches and my efforts together, this is my final solution (in the hope that it might be useful to others). It seems to me my solution is minimal and straightforward :
List<Sites> listOfSites = new ArrayList<Sites>();
for (int i = 0; i < classLists.listSites.size(); i++) {
String site = classLists.listSites.get(i);
String description = classLists.listSitesDesc.get(i);
String link = classLists.listSitesLinks.get(i);
listOfSites.add(new Sites(site, description, link));
}
Collections.sort(listOfSites, (p1, p2) -> {
return p1.getName().compareTo(p2.getName());
});
final ArrayList<String> titles = new ArrayList<>();
final ArrayList<String> descriptions = new ArrayList<>();
final ArrayList<String> links = new ArrayList<>();
for (Sites s : listOfSites) {
String name = s.getName();
String description = s.getDesc();
String link = s.getLink();
titles.add(name);
descriptions.add(description);
links.add(link);
}
Below the class Sites:
public class Sites implements Comparable<Sites> {
private String name;
private String description;
private String link;
public Sites(String name, String description, String link) {
this.name = name;
this.description = description;
this.link = link;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return description;
}
public void setDesc(String description) {
this.description = description;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
What I have is an array of String objects called Id, I'm then looping through the Id objects to get the email address associated with that Id (then concatenate them). I now want to remove the String from the array that only has a duplicate email address (ignore by looking at the Id in the String).
For example the String array contains the following Id objects:
{1, 2, 3}
Now I'm concatenating the email address associated with that Id, the String array becomes:
{1 - test#gmail.com, 2 - any#gmail.com, 3 - test#gmail.com}
So I need to remove duplicate emails (along with the Id concatenated to it) to give me this:
{1 - test#gmail.com, 2 - any#gmail.com}
Then after that I will remove the email address by using split to give me the final result of:
{1, 2}
So the issue I'm having is, it off course look for the whole string including email and Id, but I need only to look for email address then remove the whole `String from the array.
I've done this bit of code:
//Remove all duplicate email addresses from list
ArrayList<String> duplicateEmails = new ArrayList<String>();
//looping through cform.getConsumers which is a String[] array of Id's, finding email address of that Id and concatenate it and add to the array list
for (String conId : cform.getToConsumers()){
Long consId = Long.parseLong(conId);
Consumer cons = af.getSingleConsumerId(consId);
duplicateEmails.add(conId + " - " + cons.getEmail());
}
//convert arraylist to String array
String[] stringArray = duplicateEmails.toArray(new String[0]);
//remove the duplicates
Set<String> findDuplicates = new HashSet<String>(Arrays.asList(stringArray));
String[] removedEmails = findDuplicates.toArray(new String[0]);
You can do like following :
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class Testing {
public static void main(String[] args) {
HashMap<String, String> hm = new LinkedHashMap<String, String>();
String[] values = {"1","2","3"};
ArrayList<String> ar = new ArrayList<String>();
ar.add("test#gmail.com");
ar.add("any#gmail.com");
ar.add("test#gmail.com");
for (int i = 0; i<ar.size();i++) {
if (!hm.containsKey(ar.get(i)))
hm.put(ar.get(i), values[i]);
}
System.out.println(hm);
}
}
Output :
[1, 2]
Instead of writing Strings to the array, make an array of your own objects. Example:
class MyPair{
String id;
String email;
public String toString(){
return id + " - " + email;
}
}
Then you can compare emails without parsing the whole String again.
Full example with overriding hashCode() and equals(Object):
package main;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class Test {
public static void main(String[] args) {
new Test().deduplicate();
}
public class MyPair {
public final String id;
public final String email;
public MyPair(String id, String email) {
super();
this.id = id;
this.email = email;
}
public String toString(){
return id + " - " + email;
}
#Override
public boolean equals(Object obj){
if (!(obj instanceof MyPair))
return false;
if (obj == this)
return true;
return this.email.equals(((MyPair)obj).email);
}
#Override
public int hashCode(){
return this.email.hashCode();
}
}
public void deduplicate() {
List<MyPair> pairs = new ArrayList<MyPair>();
// test data
MyPair p1 = new MyPair("1", "asd#asd.com");
MyPair p2 = new MyPair("2", "qwe#qwe.com");
MyPair p3 = new MyPair("3", "asd#asd.com");
pairs.add(p1);
pairs.add(p2);
pairs.add(p3);
// just to demonstrate the overridden methods
System.out.println(p1.equals(p2));
System.out.println(p1.equals(p3));
System.out.println(p2.equals(p3));
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
// dedup will be done by HashSet
// This only works because we have overridden
// hashCode and equals!
HashSet<MyPair> deduped = new HashSet<MyPair>();
for (MyPair pair : pairs) {
deduped.add(pair);
}
System.out.println(deduped);
}
}
Output:
[2 - qwe#qwe.com, 1 - asd#asd.com]
(note the changed order! This happens because of the hashing)
Why not using 3 arrays in a way that you keep the indexes for the duplicated eMails in the third array. And then go through the first (ID's) Array and remove those indexes from it.
So you have ID array, eMail Array, Indexes to remove array.
Then release those arrays from memory :)
In that way you dont need to concat strings and then search strings
Just an idea.
I have two different string String A="example"; String B="example";
if concat both the string i am getting examplexample. Is there any possibility to avoid repetition of string with same name..??
How about this ?
if(!a.equals(b)){// or if needed use contains() , equalIgnoreCase() depending on your need
//concat
}
The Strings are not different, the same String object is assigned to two different variables ("two pointers to the same memory address").
Consider dumping all strings to a Set before concatenating, this avoids duplicates in the concatenated sequence:
Set<String> strings = new HashSet<String>();
StringBuilder resultBuilder = new StringBuilder();
for (String s:getAllStrings()) { // some magic to get all your strings
if (strings.contains(s))
continue; // has been added already
resultBuilder.append(s); // concatenate
strings.add(s); // put string to set
}
String result = resultBuilder.toString();
You can. Try something like this
private String concatStringExample1(String firstString, String secondString) {
if(firstString.equalsIgnoreCase(secondString)) { // String matched
return firstString; // or return secondString
} else { // Not matched
return firstString.concat(secondString);
}
}
or
private String concatStringExample2(String firstString, String secondString) {
if(firstString != null && firstString != null ) {
if(firstString.toLowerCase().indexOf(secondString.toLowerCase()) >= 0)
return firstString;
else if(secondString.toLowerCase().indexOf(firstString.toLowerCase()) >= 0)
return secondString;
else
return firstString.concat(secondString);
} else {
return "";
}
}
Just create a Set (It has mathematics set behaviour, it won't accept the duplicate objects)
Set<String> strings = new HashSet<String>();
//Fill this set with all the String objects
strings.add(A)
Strings.add(B)
//Now iterate this set and create a String Object
StringBuilder resultBuilder = new StringBuilder();
for(String string:Strings){
resultBuilder.append(string);
}
return resultBuilder.toString()
`
Consider the following String :
5|12345|value1|value2|value3|value4+5|777|value1|value2|value3|value4?5|777|value1|value2|value3|value4+
Here is how I want to split string, split it with + so I get this result :
myArray[0] = "5|12345|value1|value2|value3|value4";
myArray[1] = "5|777|value1|value2|value3|value4?5|777|value1|value2|value3|value4";
if string has doesn't contain char "?" split it with "|" and continue to part II, if string does contain "?" split it and for each part split it with "|" and continue to part II.
Here is part II :
myObject.setAttribute1(newString[0]);
...
myObject.setAttribute4(newString[3]);
Here what I've got so far :
private static String input = "5|12345|value1|value2|value3|value4+5|777|value1|value2|value3|value4?5|777|value1|value2|value3|value4+";
public void mapObject(String input){
String[] myArray = null;
if (input.contains("+")) {
myArray = input.split("+");
} else {
myArray = new String[1];
myArray[0] = input;
}
for (int i = 0; i < myArray.length; i++) {
String[] secondaryArray = null;
String[] myObjectAttribute = null;
if (myArray[i].contains("?")) {
secondaryArray = temporaryString.myArray[i].split("?");
for (String string : secondaryArray) {
myObjectAttribute = string.split("\\|");
}
} else {
myObjectAttribute = myArray[i].toString().split("\\|");
}
myObject.setAttribute1(myObjectAttribute[0]);
...
myObject.setAttribute4(myObjectAttribute[3]);
System.out.println(myObject.toString());
}
Problem :
When I split myArray, going trough for with myArray[0], everything set up nice as it should.
Then comes the myArray[1], its split into two parts then the second part overrides the value of the first(how do I know that?). I've overridden toString() method of myObject, when I finish I print the set values so I know that it overrides it, does anybody know how can I fix this?
I'm not quite sure what the intention is here, but in this snippet of code
secondaryArray = temporaryString.split("?");
for (String string : secondaryArray) {
myObjectAttribute = string.split("\\|");
}
if secondaryArray has two elements after the split operation, you are iterating over each half and re-assigning myObjectAttribute to the output of string.split("\|") each time. It doesn't matter what is in the first element of secondaryArray, as after this code runs myObjectAttribute is going to contain the result of split("\\|") on the last element in the array.
Also, there is no point in calling .toString() on a String object as you do in temporaryString = myArray[i].toString().
The code doesn't seem to be able to handle the possible expansion of strings in the secondary case. To make the code clearer, I would use a List rather than array.
private static String input = "5|12345|value1|value2|value3|value4+5|777|value1|value2|value3|value4?5|777|value1|value2|value3|value4+";
private void split(List<String> input, List<String> output, String split) {
for (String s: input) {
if (s.contains(split))
{
output.addAll(Arrays.asList(s.split(Pattern.quote(split)));
}
else
output.add(s);
}
}
public void mapObject(String input) {
List<String> inputSrings = new ArrayList<String>();
List<String> splitPlus = new ArrayList<String>();
inputStrings.add(input);
split(inputStrings, splitPlus);
List<String> splitQuest = new ArrayList<String>();
split(splitPlus, splitQuest, "?");
for (String s: splitQuest) {
// you can now set the attributes from the values in the list
// splitPipe
String[] attributes = s.split("\\|");
myObject.setAttribute1(attributes[0]);
....
myObject.setAttribute4(attributes[3]);
System.out.println(myObject);
}
}
I am trying to parse a String into a few variables. The String could contain these 4 tokens: "name, size, age, gender" but they don't all have to be there. Examples of possible Strings.
Example 1. "name:T-rex;"
Example 2. "name:T-rex;size:8;"
Example 3. "name:T-rex;age:4;gender:female"
I tried to do this:
private String name;
private String size;
private String age;
private String gender;
private String parse(String data)
{
String [] parts = data.split(";");
name = parts[0];
size = parts[1];
age = parts[2];
gender = parts[3];
}
But that only works if the String data contains all 4 tokens. How can I solve this problem? I really do need the 4 variables.
The best way is to parse the string into key/value pairs and then call a method that sets them by key:
/**
* Set field based on key/value pair
*/
private void setValue(String key, String value) {
switch(key) {
case "name": {
this.name = value;
break;
}
case "age" : {
this.age = value;
break;
}
//...
}
}
And call it in a programmatic way:
String[] k = "name:T-rex;age:4;gender:female".split(";");
for(String pair: k) {
String[] a = pair.split(":");
setValue(a[0], a[1]);
}
This allows you to be flexible, even to allow some keys to be missing.
Use the magic of hashmaps.
First, split the properties:
String[] parts = inStr.split( ";" );
List<String> properties = Arrays.asList(parts);
Then get name value pairs:
HashMap<String,String> map = new HashMap<String,String>();
Iterator<String> iter = properties.iterator();
for (String property : properties) {
int colPosn = property.indexof(":");
// check for error colPosn==-1
map.put( property.substring(0, colPosn), property.substring(colPosn+1) );
}
Now you can access the properties out of order, and/or test for inclusion like tis:
if(map.containsKey("name") && map.containsKey("age")) {
// do something
String name = map.get("name");
String age = map.get("age");
...