# Two Medoid-Based Algorithms for Clustering Sets
## 3 Medoid-Based Approaches
### Java Implementation  
The following gives a flavor of the Java implementation based on parallel streams [12; 19; 20] of the proposed clustering algorithms for sets. The _dataset_ and _medoids_ are represented by native arrays of \(DataObject\) instances. A _DataObject_ holds a set of items (strings) and provides the distance function (either Jaccard or cosine modified distance) and other useful methods for stream management. A \(G\_Sets\) class exposes some global parameters such as the dataset dimension \(N\), the number of clusters \(K\), the number of distinct items \(L\), the name and location of the dataset file and so forth. For generality, the implementation does not rely on the matrix of pairwise distances which is difficult to manage in large datasets. Distances among data objects are, instead, computed on demand and purposely exploit the underlying parallel execution framework. In Algorithm 4, the \(SDM()\) method of \(G\_Sets\) is shown. First, a stream is achieved from the dataset, with the \(PARALLEL\) parameter which controls whether the stream must be processed in parallel. Then, the stream is open. The intermediate \(map()\) operation works on the stream by applying a \(Function(T,R)\) lambda expression to each data object. The lambda receives a \(T\) element and returns an \(R\) result. In Algorithm 4, \(T=R=DataObject\). \(map()\) receives a \(DataObject\)\(dO\) and accumulates in its field \(dist\) the sum of distances from \(dO\) to every other object in the same cluster (controlled by the \(CID\) field of data objects). Then, the modified \(dO\) is returned. The terminal \(reduce()\) operation adds all the distances held in the data objects and returns a new \(DataObject\)\(spd\) whose \(dist\) contains the required \(SDM\). ```
publicstaticdoubleSDM(){ Stream<DataObject>pStream= (PARALLEL)?Stream.of(dataset).parallel():Stream.of(dataset); DataObjectsdm=pStream.map( dO ->| dtk=dO.getCID();dO.setDist(0); for(inti=0;i<N;++i){ if(i!=dO.getID()&&dataset[i].getCID()==k){//same cluster  dO.setDist(dO.getDist()+dO.distance(dataset[i])); } } returndO; }.reduce( newDataObject(), (d1,d2)->|DataObjectd=newDataObject(); d.setDist(d1,getDist()+d2,getDist()); returnd;} ); returnsdm.getDist(); //SDM
```  
**Algorithm 4**Stream based sum of distances to medoids (SDM) method  
An important issue in the realization in Algorithm 4 is that stream objects can be processed in parallel using the built-in fork/join mechanism [19], which splits the dataset into multiple segments and spawns a separate thread to process the data objects of a same segment. The various results are finally combined, in parallel, by the \(reduce()\) operation which returns a new \(DataObject\)\(sdm\) containing the overall sum of distances. The correctness and actual efficiency of the Java code in Algorithm 4 rests on the designer, which must absolutely avoid modifications of shared objects during the parallel execution of the lambda expressions. For example, the lambda of each \(map()\) operation in Algorithm 4 purposely modifies _only_ the received \(dO\) parameter object; thus, data interferences are completely avoided. The stream-based programming style shown in Algorithm 4 was also adopted in the implementation of K-medoids, random swap, and in all the operations which can benefit from a parallel execution. Algorithm 5 shows an excerpt of the stream-based K-medoids algorithm.