Iterating over Java Lists - how do I recognise the final element? - collections

I have a List for example
{ "in" , "out", "rec", "auth" }
... but the content of the list is not predictable.
When iterating the list list how can we know we have reached last element?
I want to apply different logic for the last element.

Example : List list = new ArrayList be the list, you need not traverse to get the last( element, you can get it by list.get(list.size()-1) and perform the logic you wanted.

The "classic" way to iterate through a Java List is to use List.iterator() to obtain an Iterator, then use the Iterator's methods to step through the list values.
This works with anything that implements Iterable, not just Lists.
// assuming myList implements Iterable<Type>
Iterator<Type> iterator = myList.iterator();
while(iterator.hasNext()) {
doSomethingWith(iterator.next())
}
Since JDK 1.5, there has been a shortcut in the language to achieve the same thing:
// assuming myList implements Iterable<Type>
for(Type item : myList) {
doSomethingWith(item);
}
However, while convenient in many situations, this syntax doesn't give you full access to all the information Iterator has.
If you want to treat the last element of the list specially, one method might be:
Iterator<Type> iterator = myList.iterator();
while(iterator.hasNext()) {
Type item = iterator.next();
if(iterator.hasNext() {
doSomethingWith(item);
} else {
// last item
doSomethingElseWith(item);
}
}
Your specific situation - creating a comma-separated string representation of the list, without a trailing comma:
Iterator<String> iterator = myList.iterator();
StringBuilder buffer = new StringBuilder();
while(iterator.hasNext()) {
buf.append(iterator.next());
if(iterator.hasNext() {
buf.append(",")
}
}
All this assumes that there's a reason you want to avoid using list.size().

You should consider using LinkedList instad of ArrayList. It has getLast() method.

Related

How to bind lists like an updating ForEach?

Here is a sample code:
public class Example3 {
class Point {
int x, y; // these can be properties if it matters
}
class PointRepresentation {
Point point; // this can be a property if it matters
public PointRepresentation(Point point) {
this.point = point;
}
}
Example3() {
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = FXCollections.observableArrayList();
points.forEach(point -> representations.add(new PointRepresentation(point)));
}
}
I have a data holder Point and a data representor PointRepresentation. I have a list of points and i would like that for each point in the list there would be an equivalent representation object in the second list. The code I gave works for the initialization but if there is any change later the above will not update.
What I am doing now is using a change listener to synchronize the lists (add and remove elements based on the change object) and it's OK but i am wondering if there's a simpler solution. I was looking for something like a "for each bind" that means: for each element in one list there is one in the other with the specified relation between them [in my case its that constructor]. In pseudocode:
representations.bindForEach(points, point -> new PointRepresentation(point));
Things I looked at: extractors for the list but that sends updates when a property in the objects they hold change and not when the list itself changes. So in my case if x in the point changes i can make an extractor that notifies it. Another thing I looked at is http://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/ListBinding.html, so maybe a custom binding does it but I don't know if it's simpler.
Also is there a similar solution for arrays instead of lists? i saw the http://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableArray.html as a possibility.
The third-party library ReactFX has functionality for this. You can do
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = LiveList.map(points, PointRepresentation::new);
This will update representations automatically on add/remove etc changes to points.

In a C# TBB: how to split a multi SingleLineTextField into seperate strings

I have a plain textfield in Tridion that can have multiple values. The itemtype is a SingleLineTextField.
In the TBB code I have the following (removed the non-essential parts):
ItemFields itemFields = new ItemFields(folder.Metadata, folder.MetadataSchema);
foreach (ItemField itemField in itemFields)
{
string itemFieldValue = string.Empty;
switch (Utilities.GetFieldType(itemField))
{
case FieldType.SingleLineTextField:
itemFieldValue = itemField.ToString();
break;
}
}
Now the result in case of two entries is just two strings with a character line break in it.
String A
String B
The method used is a generic one, which also works on other fields, so I was looking for some way to find out if a SingleLineTextField has more values in it.
You can cast the field to a SingleLineTextField type, then iterate through the Values collection, something along these lines:
SingleLineTextField field = (SingleLineTextField)itemField;
foreach(string value in field.Values)
{
// do something with value
}
// or if all you want is the count of values
int i = field.Values.Count;
Firstly, I would advise against relying on the ToString() method on objects unless it is specifically documented. In this case it works with the abstract class ItemField, but this may not always be the case.
The TOM.Net API only defines Definition and Name properties for ItemField, so you need to cast your ItemField object to something more specific.
the TextField abstract class, which SingleLineTextField inherits from, defines a ToString() method, but also Value and Values properties, which are much better suited to what you're trying to do. Looking at the documentation, we can see that Values will give us an IList<String> of the values, even if your field is not multi-valued. Perfect!
So, to answer your question, "I was looking for some way to find out if a SingleLineTextField has more values in it", you need to cast your ItemField as a TextField and check the number of Values it provides, thus:
TextField textField = (TextField)itemField;
// If you need to deal with multi-valued fields separately
if (textField.Values.Count > 1)
{
//Logic to deal with multiple values goes here
}
else
{
//Logic to deal with single valued goes here
}
// Much better... If you can deal with any number of values in a generic fashion
foreach (string value in textField.Values)
{
// Generic code goes here
}

Getting a tree node using the name and not the position

How to get a child tree node using the name and not the range of the node in the child node list .
i found this method but it uses the position of the element in the children list:
selectedNode.getChildren().get(i).
Many thanks
The collection you receive by calling getChildren() is a standard Java collection IIRC and is not indexed by name. The only ways I can think of realizing this is to create your own Node implementation or to iterate over the collection (which I think is the easiest solution).
public Node getNodeByName(String name)
{
for (Node n : selectedNode.getChildren())
{
if (name.equals(n.getName())
{ return n; }
}
return null;
}

Refactoring With Reflection

I have several methods that populate a SQLCommand objects parameter collection from an object like this
if (!String.IsNullOrEmpty(SearchObj.FirstName))
{
command.AddParameter(Fields.FirstName, SearchObj.FirstName);
}
if (!String.IsNullOrEmpty(SearchObj.LastName))
{
command.AddParameter(Fields.LastName, SearchObj.LastName);
}
if (!String.IsNullOrEmpty(SearchObj.EmailAddress))
{
command.AddParameter(Fields.EmailAddress, SearchObj.EmailAddress);
}
if (SearchObj.JobRoleId > -1)
{
command.AddParameter(Fields.JobRoleId, SearchObj.JobRoleId);
}
This can get messy as the object can have up to about 20 properties. Is there anyway using reflection to loop through each of these properties and add them all to the Sqlcommand objects Parameter collection? Bearing in mind it treats strings different to ints in that it only adds a string if its not null or empty and it only adds an int if its greater than -1.
I've not used much reflection before, so a point in the right direction would be great.
Thanks
Try using the methods listed here:
How to get the list of properties of a class?
and then loop over them adding them as you see fit.

How do I find the length of an associative array in ActionScript 3.0?

Is there a simple way to retrieve the length of an associative array (implemented as an Object) in ActionScript 3.0?
I understand that there are two primary ways of creating associative arrays in AS3:
Use a Dictionary object; especially handy when the key does not need to be a string
Use an Object, and simply create properties for each desired element. The property name is the key, and the value is, well, the value.
My application uses approach #2 (using the Object class to represent associative arrays).
I am hoping there is something more native than my for loop, which manually counts up all the elements.
You have to count them in a for loop as you do. Of course, you could make a class and stick the for loop in that class.
For some great implmentations of Collections in AS3, check these guys.
Edit 2013 Not surprisingly, links do break after time. Try this new one: http://www.grindheadgames.com/get-the-length-of-an-object.
Doing a few tests on this has actually surprised me. Here's normal use of an Array:
var things:Array = [];
things.push("hi!");
trace(things.length);
// traces 1
trace(things);
// traces hi!
Here's if we set a value to a string:
var things:Array = [];
things["thing"] = "hi!";
trace(things.length);
// traces 0
trace(things);
// traces an empty string
trace(things["thing"]);
// traces hi!
Basically if you add things using strings you're setting properties rather than actually adding to the array. Makes me wonder why Array is dynamic in this way.
So... yeah count the items with a for ... in loop!
I think you're stuck with counting them "manually".
An option would be to wrap the whole thing in a class and keep a separate variable that you update as you add/remove.
var count:int;
var key:String;
for (key in myObject)
{
count++;
}
trace ("myObject has this many keys in it: " + count);
or, alternatively, the for-each syntax (I haven't tested to see which is faster)
for each (var o:* in myObject)
{
count++;
}

Resources