Skip to content

Instantly share code, notes, and snippets.

@0guzhan
Created June 13, 2018 00:27
Show Gist options
  • Save 0guzhan/f21edf705acb79dd3686dbda0d507ccb to your computer and use it in GitHub Desktop.
Save 0guzhan/f21edf705acb79dd3686dbda0d507ccb to your computer and use it in GitHub Desktop.
Weighted Round Robin implementation
/*
* Copyright 2018 oguzhan acargil
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package demo;
import com.example.WeightedRoundRobin;
/**
* @author oguzhan acargil
*
*/
public class Test {
public static void main(String[] args) {
WeightedRoundRobin<String> wrr = WeightedRoundRobin
.<String>builder()
.add("istanbul", 0.5)
.add("ankara", 0.5)
.add("izmir", 0.0)
.build();
int i = 1;
for (String city : wrr) {
System.out.println(i++ + "." + city);
}
}
}
/*
* Copyright 2018 oguzhan acargil
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @author oguzhan acargil
*
*/
public class WeightedRoundRobin<T> implements Iterator<T>, Iterable<T>{
private WeightedRoundRobin.Entity<T>[] entities;
private int turn;
private WeightedRoundRobin(Entity<T>[] entities) {
this.entities = entities;
this.turn = 0;
}
/* (non-Javadoc)
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
return entities.length > 0;
}
/* (non-Javadoc)
* @see java.util.Iterator#next()
*/
@Override
public T next() {
Entity<T> entity = entities[turn++];
return entity.getTarget();
}
/* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<T> iterator() {
return this;
}
public static final <K> WeightedRoundRobinBuilder<K> builder() {
return new WeightedRoundRobinBuilder<>();
}
public static final class WeightedRoundRobinBuilder<K> {
private List<WeightedRoundRobin.Entity<K>> entities;
private double totalWeight;
public WeightedRoundRobinBuilder() {
entities = new LinkedList<>();
}
public WeightedRoundRobinBuilder<K> add(K target, double weight) {
entities.add(new Entity<>(weight, target));
totalWeight += weight;
return this;
}
public WeightedRoundRobin<K> build() {
List<Entity<K>> entityList = entities
.stream()
.sorted(Comparator.comparing(Entity::getWeight))
.map(this::convertWeightToPercentage)
.map(this::multiplyEntities)
.flatMap(List::stream)
.collect(Collectors.toList());
@SuppressWarnings("unchecked")
Entity<K>[] entityArray = entityList.toArray(new Entity[entityList.size()]);
return new WeightedRoundRobin<>(entityArray);
}
private List<Entity<K>> multiplyEntities(Entity<K> entity) {
return IntStream
.range(0, (int) entity.getWeight())
.mapToObj(i -> entity)
.collect(Collectors.toList());
}
private Entity<K> convertWeightToPercentage(Entity<K> entity) {
int percentageBasedWeight = (int) ((entity.getWeight() / totalWeight) * 100);
entity.setWeight(percentageBasedWeight);
return entity;
}
}
static final class Entity<T> {
private double weight;
private T target;
public Entity(double weight, T target) {
this.weight = weight;
this.target = target;
}
public T getTarget() {
return this.target;
}
public void setTarget(T target) {
this.target = target;
}
public double getWeight() {
return this.weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment