I want to create an inline list in XML. Something like this:
<numbers>
<phone>1234</phone>
<phone>5678</phone>
<phone>3456</phone>
</numbers>
The tutorial here highlights how it can be done.
Now, I have no idea about how to deal with
public Order(#Attribute(name="name") String name,
#Element(name="product") String product)
or
public OrderManager(#ElementList(name="orders") List<Order> orders) {
this.orders = orders;
}
I have never worked with lists in Java.
My case:
A database, upon querying, will fill up an array phone_numbers[x]. How am I supposed to generate the XML file like above using the values in the array and Constructor Injection?
Suppose you had a class PhoneNumbers like so:
#Root
public class PhoneNumbers {
#ElementArray(name="numbers", entry = "phone")
private String[] phones;
public PhoneNumbers(String[] phones) {
this.phones = phones;
}
}
There is no need in this case to convert to a List.
String[] phone_numbers= new String[] { "1234", "5678" }; // populate from DB instead
PhoneNumbers numbers = new PhoneNumbers(phone_numbers);
// to serialize
Serializer serializer = new Persister();
serializer.write(numbers, System.out);
This will print out the following XML:
<phoneNumbers>
<numbers length="2">
<phone>1234</phone>
<phone>5678</phone>
</numbers>
</phoneNumbers>
There is no way for the Simple framework to NOT print a root element. So you could String strip the root element if you absolutely need to just serialize the numbers element.
That's it!
Related
I have a huge group of keys like more than 10L like the below in csv file
ABA,100
ABC,200
ABCs,50
ABM,65
ABMs,86
ABS,86
AC,54
ACLU,123
ACT,56
ACTH,154
AD,644
ADC,76
ADD,10.
Do I need to create the user define an object for the above key pairs? Will it create any memoery problem for creating more than 10L user define object?
My input String looks like [ABS,AC,ACLU,ABC]
I want the output AC,ABS,ACLU,ABC based on the count.
How to achieve it in easier way of Java 1.8.
Thanks.
You could add each line of your csv to a List<String> myList
Then, you will have to create a custom Comparator in order to sort your list based on the value, so something like the following,
private void customSorting(List<String> myList) {
Collections.sort(myList, (String s1, String s2) -> {
String valuePart1 = s1.split(",")[1];
String valuePart2 = s2.split(",")[1];
return Integer.valueOf(valuePart1).compareTo(Integer.valueOf(valuePart2));
});
}
Finally, just call your method like customSorting(myList); in any place of your code you need it
Of course, you have to modify the sorted list as well to keep only the first part (before comma) for each String value but that's easy.
An alternative could also be to create a class like the following,
public class MyClass {
private String key;
private String value;
// All the getters, setters, constructors, etc
}
, and then read each line of your csv, create an equivalent MyClass POJO and add it to a List<MyClass> myList.
You have to write your own custom Comparator again for List<MyClass> in a similar way like I did for the List<String>,
private void customSorting(List<MyClass> myList) {
Collections.sort(myList, (MyClass a, MyClass b) -> {
return Integer.valueOf(a.getValue()).compareTo(Integer.valueOf(b.getValue()));
});
}
Finally, create a new list from the sorted one by keeping only the keys
Response required
{
"data" : [[1234, 55],[1264,45],[1334, 56]]
}
Model
Class Timeseries{
private List<List<Integer>> data;
}
I don't feel List of List is appropriate to achive the json response required.. But I am unable to replace it with List, where CustomObject will contain 2 integer member variables. As it will change the format of the response and send the response as data containing list of objects of type CustomObject instead of list of list..
Please suggest an alternate approch
The easiest way to reach your needed output is
class data extends ArrayList<List<Integer>> {
}
and use this code for serilization with Jackson JSON
data ts = new data();
ts.addAll(Arrays.asList(Arrays.asList(1234, 55), Arrays.asList(1264, 45), Arrays.asList(1334, 56)));
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
String result = objectMapper.writeValueAsString(ts);
System.out.println(result);
The output string will be as you need {"data":[[1234,55],[1264,45],[1334,56]]}
But, seriously, the right way here is to implement for
class Timeseries {
private List<List<Integer>> data;
}
your own com.fasterxml.jackson.databind.ser.std.StdSerializer<T> successor for Timeseries class.
UPDATE:
Just find out the easiest way to reach your needed string for class
class Timeseries {
public List<List<Integer>> data;
}
Note data field has to be either public or have a getter.
And then code
Timeseries ts = new Timeseries();
ts.data = Arrays.asList(Arrays.asList(1234, 55), Arrays.asList(1264, 45), Arrays.asList(1334, 56));
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(ts);
System.out.println(result);
will print {"data":[[1234,55],[1264,45],[1334,56]]}
You can try like this,
class CustomObject {
private int data1;
private int data2;
// getters & setters
}
Then you can modify your Timeseries as below,
private List<CustomObject> data;
You can use a list of Arrays of size 2.
I want to replace single object from List<String> with multiple objects.
List<String> list = new ArrayList<>(Arrays.asList("ROLL_NO","FULL_NAME","PERCENTAGE", "ADDRESS"));
I want to replace "FULL_NAME" with "FIRST_NAME" AND "LAST_NAME". So my list elements will be like as
"ROLL_NO",
"FIRST_NAME",
"LAST_NAME",
"PERCENTAGE",
"ADDRESS"
Collections.replaceAll() method replaces with single object only.
Is there a better way with java8 stream?
Thanks in advance.
Remove the FULL_NAME element and replace it with the FIRST_NAME and LAST_NAME elements:
List<String> list = new ArrayList<>(Arrays.asList("ROLL_NO","FULL_NAME","PERCENTAGE", "ADDRESS"));
int index = list.indexOf("FULL_NAME");
list.remove(index); //remove "FULL_NAME"
list.add(index, "LAST_NAME");
list.add(index, "FIRST_NAME");
Note the order which I am adding them. First LAST_NAME and then FIRST_NAME. This is done as setting an element at in index shifts the current element at that index to the right of the list. By doing so the elements are in the correct order as you suggested in the question.
To solve your problem, you can use remove() and add(). But a better approach will be creating a class to hold all those attributes:
public class Person{
private String rollNo;
private String firstName;
private String lastName;
private double percentage;
private String double;
//your constructors, getters & setters
}
Then use an ArrayList to hold various Person object together as one collection:
ArrayList<Person> list = new ArrayList<>();
This way, whenever you need to add/remove a record as a whole, there is no need to add/remove all related attributes manually which is very prone to mistakes.
If you list is mutable, you can use a listIterator to accomplish the same thing.
import java.util.ArrayList;
import java.util.List;
class Scratch {
public static void main(String[] args) {
final var values = new ArrayList<>(List.of(args));
final var it = values.listIterator();
while (it.hasNext()) {
final var value = it.next();
if ("FULL_NAME".equals(value)) {
it.remove();
it.add("FIRST_NAME");
it.add("LAST_NAME");
}
}
}
}
I have a list of Order objects -
class Order {
Date date;
float amount;
String companyCode;
}
List<Order> orders = /* Initialize with list of order objects with valid data */
I have a list of Company objects -
class Company {
String name;
String code;
String address;
}
List<Company> companies = /* Initialize with list of company objects with valid data */
I need a to create a map of companyCode and name.
Is there some library that would allow me to write code like this (where BeanSearch is the hypothetical library class)?
Map<String, String> codeAndName = new HashMap<String, String>();
for(Order o: orders) {
codeAndName.put(o.getCompanyCode(),
BeanSearch.find(companies, "code", o.getCompanyCode).getName());
}
Alternatively is there another good way to do it?
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html should work for you right? Specifically you can use the find method
Is it possible to store a list of integers in a single field of the respective entity table with standard JPA 2?
#Entity
#Table(name="tbl_myentities")
public class MyEntity {
#ElementaryCollection
#Column(name="vals") // in table tbl_myentities
private List<Integer> vals;
It is not possible to store multiple values in a single field. Whats the reason behind storing them in a single field?
A way could be to use a field of type String and add all integers there in a comma separated list and join/explode in getters and setters:
private String vals;
public setVals(int vals[])
{
// this.vals = Iterate vals[] and create a comma separated string
}
public int[] getVals()
{
// vals.split(",") to get a list of Strings, then typecast/parse them to ints before returning
}
Using the #ElementCollection annotation and #CollectionTable to control the mappings requires a separate table to store the values in.
#ElementCollection
private Collection<Integer> integers;
Read more about element collections on on http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection
Similar question here Does JPA #ElementCollection annotation always produce an one-to-many relationship?
You can create a converter and use it with the annotation #Converter.
This converter must implement AttributeConverter which is a generic interface with two methods convertToDatabaseColumn and convertToEntityAttribute.
It is pretty easy to work with, you can check here: jpa independent custom type mapping / javax.persistence.x alternative to org.hibernate.annotations.Type and org.hibernate.annotations.TypeDef
You can store all the vals in a String field, separated with a comma, and change associated getter and setter like that :
public List<Integer> getVals() {
List<Integer> lstVals = new ArrayList<Integer>();
int val = 0;
for(String field : this.vals.split(",")) {
try {
val = Integer.parseInt(field);
}
// If the String contains other thing that digits and commas
catch (NumberFormatException e) {
}
lstVals.add(val);
}
return lstVals;
}
public void setVals(List<Integer> vals) {
String newVals = "";
for(int i : vals) {
newVals.concat(String.valueOf(i));
}
this.vals = newVals;
}
I don't think that's possible. Because you can not have a column in a database table that allows you to store list of integers.
What you can do is use a string type field instead of list of integers -
#Column(name="vals") // in table tbl_myentities
private String vals;
And do the conversion to string from list of integers and back manually before you save your entity and after you have read your entity.
Maybe a #Lob could suit you ? (despite what it imply)
#Lob
ArrayList<String> vals;
(note that your collection must be explicitly an ArrayList)