A sorted set is a collection of unique elements (no duplicates) of a predefined order.

This diagram shows the classes and interfaces relevant to a sorted set collection in the Progress.Collections framework.

This table describes the classes and interfaces specific to sorted sets (for collection-specific interfaces, see Collections in object-oriented ABL).

Class or interface Description
Progress.Collections.IComparable <T> interface This interface defines a method for specifying the default sort order for a SortedSet<T>.
Progress.Collections.IComparer <T> interface This interface defines a method for specifying a custom sort order for a SortedSet<T>.
Progress.Collections.ISet<T> interface This interface is the root interface for all set collection classes and indicates that the collection conforms to specific rules about how duplicates are handled.
Progress.Collections.SortedSet<T> class This class represents a strongly-typed collection of unique objects that is maintained in sorted order.
Progress.Collections.SortedSetIterator<T> class This class represents the type of object returned by the GetIterator() method on a SortedSet<T> class and allows the traversal of elements in the set.

The order of elements in a SortedSet is determined by the comparer implementation for the set. You determine the order of elements, either by providing the class's natural ordering (that is, the class type for the elements needs to implement the IComparable<T> interface), or by providing a comparer object that implements the IComparer<T> interface.

The SortedSet<T> class implements the properties and methods defined in the ICollection<T> interface and two additional properties (First and Last).

The SortedSet’s default comparer implementation calls the CompareTo() method on the class implementing the IComparable<T> interface, to determine the location of the newly inserted element, if a comparer was not specified in the constructor. If a comparer was specified, the comparer’s Compare() method is always called instead and is the only one called and it does not matter if the element itself implements IComparable or not.

The SortedSet’s default comparer implementation does not allow the unknown value (?) or invalid object references to be added into the collection. If using a custom comparer, then it is up to the comparer implementation to define the behavior for the unknown value (?).

The following rules also apply to the SortedSet implementation:
  • The SortedSet implementation supports any object-oriented ABL object, including .NET objects. However, you must specify your own comparer when adding .NET objects to a SortedSet (that is, natural ordering is not supported in this case).
  • Duplicate elements are not allowed. This is dependent on the value returned from the comparer implementation (whether using the default comparer or a custom one). If the Compare()/CompareTo() method returns 0, an object is considered to be in the set already, and is not added again (that is, the existing one remains in the set).
  • The order of the elements is maintained when elements are added or removed, based on the comparer implementation.
  • The Contains(), Get(), and Remove() methods determine equality of the element based on the value returned by the comparer implementation (whether using the default comparer or a custom one).
  • The SortedSet has a reference to any object added to it, which prevents garbage collection of such added object until that reference no longer exists.
  • Changing the sort values of existing elements is not supported and may lead to unexpected behavior (that is, the sorting order or uniqueness of the set is not guaranteed).
  • It is not safe to delete objects that are elements of the set. Doing so potentially invalidates the complete collection as the sorting algorithm may no longer be able to guarantee consistency or uniqueness of the set.

    If a deleted object reference is encountered during any operation that needs to access properties of the element or invoke a method on that element, the operation fails, and an error is raised indicating that a deleted object reference was encountered. That includes the comparer object, if one was specified for the SortedSet collection.

Serialization and remote parameter passing

A sorted set collection object can be serialized using the present forms of serialization, which include binary and JSON serialization, via the built-in Progress.IO.BinarySerializer and Progress.IO.JsonSerializer classes, respectively.

You can also pass such objects to, or from, a Progress Application Server (PAS) for OpenEdge remote call.

Serialization and remote parameter passing for object-oriented ABL objects require that all objects are marked as SERIALIZABLE, therefore, the objects inside the collection also need to be SERIALIZABLE, otherwise an error is raised during object serialization.

Example: SortedSet collection

The following is an example of a class called MyString that implements Progress.Collections.IComparable. The class provides a default comparer (via the CompareTo() method), that sorts the elements in alphabetical order of the strings passed in.

class MyString implements Progress.Collections.IComparable<Mystring>: 

  define property Value as char get. private set.

  constructor MyString(INPUT pValue as CHAR).
    if pValue = ? then
      return error "Unknown value not supported”.
    THIS-OBJECT:Value = pValue.
  end.

  method public integer CompareTo(otherObject as MyString). 

    if this-object = otherObject OR 
      this-object:Value = otherObject:Value then
        return 0.
    else if this-object:Value < otherObject:Value then
        return -1. // current object sorts lower

    // current object sorts higher
    return 1.
  end.

end.

The following example shows the usage of a SortedSet collection in ABL, using the MyString class above.

var Progress.Collections.ISet<MyString> stringSet.
var Progress.Collections.IIterator<MyString> iterator.
var MyString name1.

stringSet = new Progress.Collections.SortedSet<MyString>().

// Add 4 elements to the set
stringSet:Add(new MyString("Thomas")).
stringSet:Add(new MyString("George")).
stringSet:Add(new MyString("Paul")).
stringSet:Add(new MyString("John")).

// Same value will not be added to the set
if stringSet:Add(new MyString("George")) eq false then
  message "George is already in the list".

// Print out the number of elements in the set
message "Count:" stringSet:Count.

name1 = new MyString("Paul").

// Remove one element from the set if it exists
if stringSet:Contains(name1) then 
  stringSet:Remove(name1).

// Iterate over the entries in the set
// which should show George, John and Thomas
iterator = stringSet:GetIterator().
repeat while iterator:MoveNext():
  message iterator:Current:ToString().
end.