Nova versão do projeto disponivel para download(ver pagina Towel Project), os tutoriais explicados aqui também estão na Wiki do projeto.
MarkUtils V2.8
Estudei um pouco de arvores e resolvi refazer completamente a classe Expression para resolver expressoes matematicas.
E agora ela esta empacotada nesta nessa nova versão.
Agora ela além de resolver as expressões normais, podem ser usadas varias funções como as da classe Math.
E elas são: cos, sin, tan, acos, asin, atan, sqrt, sqr, log, exp, floor, ceil, abs e neg
Para usar na expressão coloque função(valor)
Algo como: cos(10)*tan(2*2)+log(1)
Fora isso ainda foi acrescentado uma função random ‘rnd’, que pode ser usada como variavel aleatoria.
Ex: ‘rnd(42)’, retorna um valor entre 0 e 41.99
Fora isso a classe CollectionsUtil tem alguns métodos novos que é algo que estou desenvolvendo para depois usar em outra parte do projeto, mas já é bem util.
CollectionsUtil.split(List l, String field)
Esse método retorna uma List com os valores do atributo ‘field’ que estão em cada objeto da lista ‘l’.
Por exemplo, usando o modelo Person
public class Person {
private String name;
private int age;
public Person(String str, double d) {
this.name = str;
this.age = (int) d;
}
}
Se tivermos uma Lista de Person e quisermos uma lista com todas as idades, é possivel fazer o seguinte.
List<Person> list = new ArrayList<Person>();
list.add(new Person("A", 10.0));
list.add(new Person("B", 20.0));
list.add(new Person("C", 30.0));
list.add(new Person("D", 40.0));
list.add(new Person("E", 50.0));
List<Double> ages = CollectionsUtil.split(list, "age");
E ‘ages’ terá os elementos [10.0,20.0,30.0,40.0,50.0].
Mas o mais interessante com isso, é a novo package collections.aggr.
Ela permite aplicar uma função sobre todos os elementos de uma lista e obter o resultado. Funções como, soma, média ou qualquer coisa de acordo com a implementação de AggregateFunction.
Para usa-la é simples:
List<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
Integer sum = CollectionsUtil.aggregate(new FuncSum(), list).intValue();//.intValue por que FuncSum retorna Number
Double avg = CollectionsUtil.aggregate(new FuncAvg(), list).doubleValue();
System.out.println("sum = " + sum);
System.out.println("avg = " + avg);
As classes FuncSum(Soma) e FuncAvg(Média) já estão implementadas no projeto e existe uma terceira, FuncConcat que concatena Strings.
Também é possivel aplicar sobre uma coleção de objetos diferentes do que a Func espera, para isso, usar o método.
CollectionsUtil.aggregate(List l, AggregateFunc func, String field)
Que o resultado será a função aplicada sobre todos os objetos resultantes de CollectionsUtil.split(l, field).
Sobre a AggregateFunction, para criar novas implementações de funções, criar uma implementação dessa classe, sua assinatura é:
package com.towel.collections.aggr;
/**
* Functions to work over an object, the object is of the type T
*
* @author marcos.vasconcelos
*/
public interface AggregateFunc<T> {
/**
* Init this Func with the initial values.
* This method is called when a new Calculation over a Collection is going to ve initiated.
* When implementing, reset all values to it initial value.
*/
public void init();
/**
* Called over each value in a List.
* This method should calculate the new value with a previous value.
* @param obj
*/
public void update(T obj);
/**
* Called when the iteration is over and the final value is done.
* @return The value of the function apllied over all objects passed in Func.update
*/
public T getResult();
}
O método init é chamado antes das iterações.
O método update é chamado com cada objeto que a função trabalha.
O método getResult é chamado depois das iterações, e deve retornar o resultado do processo.
Como exemplo, essa é a implementação para média.
package com.towel.collections.aggr;
public class FuncAvg implements AggregateFunc<Number>{
private Number x;
private int total;
@Override
public void update(Number obj) {
x = new Double(x.doubleValue() + obj.doubleValue());
total++;
}
@Override
public Number getResult() {
return x.doubleValue() / total;
}
@Override
public void init() {
x = new Double(0);
total = 0;
}
}
E com isso, termino o changelog da versão 2.8 do projeto.
Se alguém criar uma AggregateFunction interessante e quiser coloca-la no projeto é só me enviar.
E outra, siga @MarkyHitchhiker no twitter, atualizações do projeto e coisas uteis serão informadas lá.