I have a YAML file that looks like this:
foo:
bar:
- entry1: 1
entry2: a
- entry1: 2
entry2: b
(Where the actual list is much longer.) I'm reading this file using Apache Configuration2's YAMLConfiguration. I can see the data in the internal data structures used in Apache Configuration2, but I can't figure out how to get this list out. I actually have a class that matches the structure of the list elements, which is what I'd really like to read into:
class MyListEntry {
public int entry1;
public String entry2;
}
How can I get the data YAMLConfiguration into a List<MyListEntry>?
Here's the solution I found (note this works for any HierarchicalConfiguration, not just YAMLConfiguration)
// this will return a list of List<HierarchicalConfiguration<ImmutableNode>>, one entry for each element of the list
var subConfigList = hierarchicalConfig.configurationsAt("foo.bar");
List<MyListEntry> myListEntries = new ArrayList<>(subConfigList.size());
// iterate over the subconfigs and pull out the specific values of interest
for(var subConfig : subconfigs) {
MyListEntry myListEntry = new MyListEntry();
myListEntry.entry1 = subConfig.getInt("entry1");
myListEntry.entry2 = subConfig.getString("entry2");
myListEntries.add(myListEntry);
}
Related
I was learning flatbuffers from this link , there was no example to demonstrate how to store dictionary(map). There was a mention of "Storing dictionaries in java/Csharp" in this link , but i did not understand much about it. I am from java background. Any example of how to store dictionary/map in flatbuffers in java would be helpful
I realize this is an old question but I came across it when I was trying to figure out the same thing. Here is what I did to get a "dictionary/map"
Schema File
namespace com.dictionary;
table DataItem{
keyValue:string(key);
name:string;
age:int;
codes[string];
}
table DictionaryRoot{
items:[DataItem];
}
root_type DictionaryRoot;
When you run this through the FlatBuffers compiler flatc -j schema.fbs it will produce two Java files, one named DictionaryRoot.java, the other named DataItem.java.
In your Java application
Using those two generated Java files you will need to construct the buffer. This has to be done from the innermost data to the outermost. So you need to construct your DataItems (and keep track of their offsets) before your DictionaryRoot.
In this example, let's assume that you have a map of Objects in Java that you need to create the buffer from.
List<Integer> offsets = new ArrayList<>();
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
for (Entry<String, DataObj> entry : map.entrySet()) {
DataObj dataObj = entry.getValue();
// use the builder to create the data and keep track of their offsets
int keyValueOffset = builder.createString(entry.getKey());
int nameOffset = builder.createString(dataObj.getName());
int ageOffset = dataObj.getAge();
int[] codesOffsets = dataObj.getCodes().stream().mapToInt(builder::createString)
.toArray();
// use the builder to create a vector using the offsets from above
int codesVectorOffset = DataItem.createCodesVector(builder, codesOffsets);
// now with all the inner data offsets, create the DataItem
DataItem.startDataItem(builder);
DataItem.addKeyValue(builder, keyValueOffset);
DataItem.addName(builder, nameOffset);
DataItem.addAge(builder, ageOffset);
DataItem.addCodes(builder, codesVectorOffset);
// ensure you 'end' the DataItem to get the offset
int dataItemOffset = DataItem.endDataItem(builder);
// track the offsets
offsets.add(dataItemOffset);
}
// use the builder to create a sorted vector from your offsets. This is critical
int sortedVectorOffset = builder.createSortedVectorOfTables(new DataItem(),
offsets.stream().mapToInt(Integer::intValue).toArray());
// now with your sorted vector, create the DictionaryRoot
DictionaryRoot.startDictionaryRoot(builder);
DictionaryRoot.addItems(builder, sortedVectorOffset);
int dictRootOffset = DictionaryRoot.endDictionaryRoot(builder);
// signal to the builder you are done
builder.finish(dictRootOffset);
// Write data to file
FileOutputStream outputStream = new FileOutputStream("output.bin");
outputStream.write(builder.sizedByteArray());
outputStream.close();
I hope that will help someone else along their journey using FlatBuffers.
I have a CSV file that links a region to a zip code. It looks like this (lowest-zip, highest-zip, region):
1600,1799,1
1800,1899,1
4300,4699,1
2820,2839,2
2850,2879,2
2930,2949,2
5600,5819,3
5850,6514,3
6516,6549,3
6800,6849,3
I need a function that returns the region based on the zip code. Something like this:
foo = getRegion(1600) // foo is set to 1
bar = getRegion(1642) // bar is set to 1
baz = getRegion(4351) // baz is set to 2
qux = getRegion(1211) // qux is set to null
The way I currently implemented this is using a HashMap. When I read the CSV I iterate over every value between 1600 and 1799 and create a key-value pair for each zip code / region combination and repeat that for every row in the CSV. The result is a HashMap looking like this:
1600,1
1601,1
1602,1
...
1799,1
1800,2
1801,2
...
This creates a large HashMap, which does work. Is there a more (memory) efficient implementation than exploding this small table to a large HashMap?
Something like below will help -
class ZipRange {
int start;
int end;
}
// Fill up this map parsing through csv
Map<ZipRange, Integer> zipToRegion;
int zipToSearch = 2870;
// Create method which returns integer which corresponds to region
for (ZipRange zip : zipToRegion.keySet()) {
if (zipToSearch >= zip.start && zipToSearch <= zip.end) {
return zipToRegion.get(zip);
}
}
return -1;
I think you want a segment tree
I was wondering if there was anyway to treat col_1,col_2...etc as a list rather than separate elements, using the SIMPLE XML Library for Android. I have been reading a bit about substitutions but I'm still confused.
Current Format :
<box-headers
dataTable="boxscore"
col_1="FINAL"
col_2="1"
col_3="2"
col_4="3"
col_5="4"
col_6="5"
col_7="6"
col_8="7"
col_9="8"
col_10="9"
col_11="R"
col_12="H"
col_13="E">
table
</box-headers>
I want to be able to parse out the col's as a list of some sort so I can handle any number of cols. Is this possible?
As ng said before: Use a Converter for this. Simple is brilliant in letting you customize every step of processing (while on the other hand it's possible to let you (de-)serialize even complex structures with some lines of code).
So here's an example:
A Class that will hold the values from the list:
#Root(name = "example")
#Convert(value = ListConverter.class) // Specify the Converter that's used for this class
public class Example
{
// This element will be set with the values from 'box-headers' element
#ElementList(name = "box-headers")
private List<String> values;
// This constructor is used to set the values while de-serializing
// You can also use setters instead
Example(List<String> values)
{
this.values = values;
}
//...
}
The Converter:
public class ExampleConverter implements Converter<Example>
{
#Override
public Example read(InputNode node) throws Exception
{
List<String> list = new ArrayList<>(); // List to insert the 'col_' values
NodeMap<InputNode> attributes = node.getAttributes(); // All attributes of the node
Iterator<String> itr = attributes.iterator();
while( itr.hasNext() ) // Iterate over all attributes
{
final String name = itr.next(); // The name of the attribute
if( name.startsWith("col_") ) // Check if it is a 'col' attribute
{
// Insert the value of the 'col_' attribute
list.add(attributes.get(name).getValue());
}
}
// Return the result - instead of a constructor you can use setter(s) too
return new Example(list);
}
#Override
public void write(OutputNode node, Example value) throws Exception
{
// TODO: Implement serializing here - only required if you want to serialize too
}
}
How to use:
// Serializer, don't forget `AnnotationStrategy` - without it wont work
Serializer ser = new Persister(new AnnotationStrategy());
// Deserialize the object - here the XML is readen from a file, other sources are possible
Example ex = ser.read(Example.class, new File("test.xml"));
This example uses only col_xy attributes, everything else is dropped. If you need those values too it's easy to implement them. You only have to retrieve them from the InputNode and set them into your output.
I am not sure if it possible or not but I think it can be done using JSONArray.put method.
Heres my problem:
I have got two lists:
ArrayList<Students> nativeStudents;
ArrayList<transferStudents> transferStudents = nativeStudents.getTransferStudentsList();
The JSON that I generate with transferStudents list is right here: http://jsfiddle.net/QLh77/2/ using the following code:
public static JSONObject getMyJSONObject( List<?> list )
{
JSONObject json = new JSONObject();
JsonConfig config = new JsonConfig();
config.addIgnoreFieldAnnotation( MyAppJsonIgnore.class );
if( list.size() > 0 )
{
JSONArray array = JSONArray.fromObject( list, config );
json.put( "students", array );
}
else
{
//Empty Array
JSONArray array = new JSONArray();
json.put( "students",
array );
}
return json;
}
Now what I want to get is JSON data with following structure: http://jsfiddle.net/bsa3k/1/ (Notice the tempRollNumber field in both array elements).
I was thinking of doing: (The if condition here is used for a business logic)
if(transferStudents.getNewStudentDetails().getRollNumber() == nativeStudents.getNativeStudentDetails.getStudentId()){
json.put("tempRollNumber", transferStudents.getNewStudentDetails().getRollNumber());
}
but this would add tempRollNumber outsite the array elements, I want this JSON element to be part of every entry of students array.
PS: I cant edit the transferStudents class in order to add tempRollNumber field.
Since no one has come up with anything better I'll turn my comments above into an answer.
The best way to handle this is to create an object model of your data and not create the JSON output yourself. Your app server or container can handle that for you.
Though you cannot change the objects you receive in the List you can extend the object's class to add your own fields. Those fields would then appear in the JSON when you marshall it.
I got a problem regarding parsing XML data. I have divided my program into 3 different java files, each containing a class. One of them is rssparser.java. This file holds a function called iterateRSSFeed(String URL), this function returns a string containing the parsed description tag. In my main.java files where my main method is, I call this iterateRSSFeed function this way:
rssparser r = new rssparser();
String description = r.iterateRSSFeed();
And then I am planning to add this String to a JLabel, this way:
JLabel news = new JLabel(description);
which obviously works great, my program runs. BUT there are more description tags in my XML file, the JLabel only contains one(1) parsed description tag. I should say that my return statement in the iterateRSSFeed function is "packed" in a for-loop, which in my head should return all of the description tags. But no.
Please ask if something is uncleared or showing of the source code is a better way to provide a solution to my answer. Thanks in advance! :)
When Java executes a return statement, it will leave the method, and not continue running the loop.
If you want to return multiple values from a method, you have to put them in some object grouping them together. Normally one would use a List<String> as return type.
Then your loop will fill the list, and the return statement (after the loop) can return the whole list at once.
If you want to have one large string instead of multiple ones, you'll have to merge them into one.
The easiest would be to simply use the .toString() method on the list, this will give (if you are using the default list implementations) something like [element1, element2, element3].
If you don't like the [,], you could simply concatenate them:
List<String> list = r.iterateRSSFeed();
StringBuilder b = new StringBuilder();
for(String s : list) {
b.append(s);
}
String description = b.toString();
This will give element1element2element3.
As Java's JLabel has some rudimentary HTML support, you could also use this to format your list as a list:
List<String> list = r.iterateRSSFeed();
StringBuilder b = new StringBuilder();
b.append("<html><ul>");
for(String s : list) {
b.append("<li>");
b.append(s);
b.append("</li>");
}
b.append("</ul>");
String description = b.toString();
The result will be <html><ul><li>element1</li><li>element2</li><li>element3</li></ul>, which will be formatted by the JLabel as something like this:
element1
element2
element3