Towel – Release 1.2.2

30 06 2011

Hoje está sendo liberado um release do projeto Towel com uma pequena alteração enviado por Paulo Henrique.

A unica diferença é que agora é possivel mudar o texto do botão que aparece no Popup do CalendarView.

Para isso, basta usar o método setTodayString do CalendarView.

Ex:

CalendarView view = new CalendarView();
view.setTodayString("Hoje");

Para baixar a nova versão, basta entrar na pagina Towel Project do blog e seguir o link para o github.





CalendarView

1 06 2011

Esse artigo é sobre uma classe do projeto Towel, para utiliza-la, baixe a biblioteca na pagina Towel Project desse blog.

Esse componente foi feito em 1999 pelo meu professor de Java enquanto ele fazia estagio na area, por esse motivo eu desculpo ele por ter usado null-layout, mas refatorei ele para ser mais generico e independente de LayoutManagers.

O CalendarView é um componente que exibe um JTextField e um JButton juntos.
O JTextField serve para digitar dadas no formato ‘dd/MM/yyyy’ e o JButton abre uma JWindow que permite escolher a data em um calendario.

Para utiliza-lo é bem simples:

import java.awt.event.*;
import javax.swing.*;

import com.towel.swing.calendar.CalendarView;

public class CalendarViewTest {
	public CalendarViewTest() {
		JFrame frame = new JFrame("CalendarView");
		JPanel content = new JPanel();
		final CalendarView view = new CalendarView();
		JButton button = new JButton("X");
		content.add(view);
		content.add(button);
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println(view.getSelectedDate());
			}
		});

		frame.setContentPane(content);
		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

	public static void main(String[] args) {
		new CalendarViewTest();
	}
}

Esse codigo exibe a seguinte janela:

E quando pressionado o botao “..” a JWindow aparece com o DatePicker para escolher uma data.

Escolhendo alguma data o valor é exibido no campo de texto.

Para obter o valor que o usuario digitou (em uma ação por exemplo), temos dois métodos:

  • getText() que retorna o texto do TextField
  • getSelectedDate() que retorna um objeto Calendar com a data selecionada pelo usuario.
  • E no caso do código de exemplo, ao pressionar ‘X’ é exibido o toString do objeto Calendar que for escolhido.

    Como sempre, ainda é possivel melhorar esse componente, e essa é a lista do que já pode ser feito:

  • Um Layout melhor para o JWindow.
  • Internacionalizar os textos (nome do mês, inicial do dia, botão “hoje”)
  • Poder digitar datas no formato MM/dd/yyyy




  • Towel – Release 1.2

    25 05 2011

    Hoje dia 25/05 está sendo liberado o novo release do projeto Towel.

    As novidades são:

    • FieldResolver consegue obter/setar os valores dos atributos através da hierarquia do objeto;
    • Não é obrigatório declarar as anotações @Resolvable em todos os atributos, nesses casos o DefaultFormatter vai ser utilizado e o FieldHandler será o FieldAcessHandler padrão;
    • Um novo componente enviado pelo meu professor de Java foi incluido no pacote com.towel.swing sob o nome de CalendarView, que é um DatePicker para Swing; (Artigo em breve)

    Para baixar a nova versão, basta entrar na pagina Towel Project do blog e seguir o link para o github.

    Mais uma coisa está acontecendo hoje:

    Dia 25/05 é o Towel Day, em homenagem a Douglas Adams.
    Esse release foi planejado. ;)

    Abraço a todos, e feliz dia da toalha!





    JTableView

    14 02 2011

    Algo que eu planejava a algum tempo é oferecer um modo onde seja possivel ter colunas em uma JTable com valores agregados como, soma, média, menor, maior e etc.., foi com essa intenção que criei as AggregateFunctions. O model que faz isso para as colunas está pronto, e é o AggregateModel.
    Mas encontrei alguns desafios não triviais para fazer isso funcionar, não existe nem na JTable nem no JScrollPane um modo de adicionar um footer, a unica maneira que pensei para resolver isso é criando uma classe que estende JPanel que tenha um JScrollPane com uma “Main Table” e outro com uma linha fixa com o model de agregação dos valores da tabela principal. Então para encapsular essa “gambiarra” criei a classe JTableView, com ela é possivel utilizar esse novo recurso. Mas ainda tem alguns poucos defeitos que ainda não consegui resolver (uma contribuição se alguem souber é bem vinda ^^).

    Para utiliza-la, é necessario instanciar o JTableView com um modelo qualquer e depois as funções que serão utilizadas nas colunas do footer.

    Como exemplo, usaremos o modelo “Person”  para exibir alguns valores e aplicaremos algumas funções nas colunas.

    Person.java

    public class Person {
    	@Resolvable(colName = "Name")
    	private String name;
    	@Resolvable(colName = "Age")
    	private int age;
    	@Resolvable(colName = "Live")
    	private boolean live;
    
    	public Person(String name, int age, boolean live) {
    		this.name = name;
    		this.age = age;
    		this.live = live;
    	}
    }
    

    Com isso criamos o modelo e adicionamos alguns dados.
    PS:Para quem não sabe como funciona o ObjectTableModel pode ver aqui.

    		ObjectTableModel model = new ObjectTableModel(
    				new AnnotationResolver(Person.class), "name,age,live");
    
    		model.setEditableDefault(true);
    
    		model.add(new Person("A", 10, true));
    		model.add(new Person("B", 20, true));
    		model.add(new Person("C", 30, false));
    		model.add(new Person("D", 40, true));
    		model.add(new Person("E", 50, true));
    

    PS: JTableView não funciona apenas com o ObjectTableModel, mas ele é o mais simples de ser utilizado em qualquer ocasião.

    Agora com o modelo pronto, só precisamos criar o JTableView e colocar as funções de agregações que queremos na tabela.

    		JTableView view = new JTableView(model);
                    //Os indices são 0 based.
    		view.getFooterModel().setFunction(0, new FuncConcat("-"));
    		view.getFooterModel().setFunction(1, new FuncSum());
    

    PS: Para saber como funciona a API de AggregateFunctions, ver em CollectionsUtils.

    Não é necessario ter uma função para todas as colunas, estas ficaram em branco.

    Agora só basta colocar esse componente em algum lugar, como em um JFrame e exibi-lo.

    		JFrame frame = new JFrame();
    		frame.getContentPane().add(view);
    
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setVisible(true);
    

    Com isso temos o seguinte resultado.

    Ao alteramos os valores na tabela principal o novo resultado é calculado no footer.

    Como eu disse, este componente não está perfeito, ele tem suporte a re-alocação de colunas, caso voce esteja clicando no header da main table e arrastando a coluna para outro lugar.

    Mas ela não tem suporte para resize de colunas, o resultado se esticar algumas colunas vai ser bem estranho, se alguém souber como resolver será muito interessante para o projeto.
    Então ainda não indico utilizar este componente a não ser em caso que deixem a tabela fixada e sem suporte para mudar o tamanho das colunas, uma versão melhorada desse componente vai ser liberado assim que for arrumado estes erros pendentes.





    DynamicFormatter

    12 02 2011

    Essa classe é uma contribuição de Felipe Priuli para o projeto Towel, e também foi ele que escreveu este artigo de como utiliza-lo.

    Esta classe implementa com.towel.bean.Formatter e foi criado, primeiramente, para ser utilizado no ObjectComboBoxModel, permitindo criar um Formatter dinamicamente para
    as classes que serão utilizada como model de um ComboBox. Em outras palavras, ao invés de criar um Formatter para cada classe é possível utilizar este Formatter
    para representar as classes de maneira genérica.

    Ele funciona permitindo adicionar FieldResolvers a uma lista que será utilizada para obter os valores dos objetos do modelo, para ver uma explicação detalhada de como o FieldResolver funciona, veja no artigo sobre ObjectTableModel.

    Vamos para o exemplo:

    Primeiro! Vamos criar a classe Person:

    public class Person {
            private String name;
            private int age;
            public Person(String str, double d) {
                    this.name = str;
                    this.age = (int) d;
            }
            public String toString() {
                    return "Name: " + name + " age: " + age;
            }
    }
    

    Nós queremos mostrar informações sobre a pessoa em cada iten do JComboBox, mas ao inves de criar um Formatter para a classe Pessoa, vamos utilizar o DynamicFormatter.

    Abaixo um exemplo de como criar um JComboBox de ‘Person’ utilizando o model ObjectComboBoxModel com o DynamicFormatter:

    import javax.swing.*;
    
    import com.towel.awt.ann.*r;
    import com.towel.bean.DynamicFormatter;
    import com.towel.combo.swing.ObjectComboBoxModel;
    import com.towel.el.FieldResolver;
    
    public class ComboBoxDynamicFormatterTest extends JFrame {
    	private ObjectComboBoxModel model;
    	@Action(method = "showPerson")
    	private JButton button;
    
    	public ComboBoxDynamicFormatterTest() {
    		super("ComboBoxModel");
    		model = new ObjectComboBoxModel();
    
    		DynamicFormatter formatter = new DynamicFormatter(
    				Person.class, " - ");
    		formatter.addField(new FieldResolver(Person.class, "name"));
    		formatter.addField(new FieldResolver(Person.class, "age"));
    
    		model.setFormatter(formatter);
    		// Adicionado as classes Person no model
    		model.add(new Person("A", 10.0));
    		model.add(new Person("B", 20.0));
    		model.add(new Person("C", 30.0));
    		model.add(new Person("D", 40.0));
    		model.add(new Person("E", 50.0));
    
    		JComboBox combo = new JComboBox(model);
    		JPanel cont = new JPanel();
    		cont.add(combo);
    		cont.add(button = new JButton("Show"));
    		setContentPane(cont);
    		pack();
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setLocationRelativeTo(null);
    		setVisible(true);
    
    		new ActionManager(this);// Necessary to map @Action to the method
    	}
    
    	private void showPerson() {
    		Person p = model.getSelectedObject();
    		System.out.println(p.toString());
    	}
    
    	public static void main(String[] args) {
    		new ComboBoxDynamicFormatterTest();
    	}
    }
    

    Ele ainda tem a vantagem que se for necessario exibir um campo que seja GregorianCalendar, é possivel adicionar o Formatter ao FieldResolver desse atributo para exibir um valor mais amigavel do que o valor padrão do toString.

    Os métodos utilizados para criar os itens em um ComboBox de maneira generica, pela classe DynamicFormatter são:

    • addField(FieldResolver) : Ele permite adicionar um resolver a lista que será utilizada para montar a String que representa o objeto.
    • format(Object) : O método ‘format’ faz a conversão do objeto para texto. O texto é aquele que será mostrado no item do ComboBox.
    • setSeparator(String) : Este método permite que você indique o texto que irá separar o texto dos itens e é usado quando existir mais de um campo que irá aparecer no item de JComboBox
    • getFieldList() : Este método retorna uma lista de FieldResolver. O FieldResolver é responsável por obter os valores dos atributos (Fields) dos objetos, estes valores são então mostrados nos itens combobox.




    JImagePanel

    11 02 2011

    Essa classe está no projeto Towel, para utiliza-la, entre na pagina “Towel Project” e baixe a versão mais atual para adicionar ao classpath.

    JImagePanel é uma classe criada pelo ViniGodoy, é um JPanel que tem uma imagem de background no fundo e modificada por mim para ter suporte a exibir uma sequencia de imagens através do tempo.

    Com ela, é possivel criar telas em Swing com imagens de fundo e ainda ter componentes por cima, diferente do que seria possivel com um JLabel, e ela é extremamente simples de usar.

    Para utilizar:

    • Criar uma instancia com uma ou varias imagens;
    • Escolher o FillType, opcional, este é o modo de como a imagem vai se comportar quando a area disponivel for maior que ela, as opções são: RESIZE (crescer), CENTER (centralizado), SIDE_BY_SIDE (Lado a lado, assim como no Desktop do windows). Por default o FillType é RESIZE;
    • Adicionar ela a um Container, como um JFrame por exemplo;
    • Adicionar componentes sobre ela, isso é feito assim como em um JPanel;
    • Exibi-la.

    O seguinte código representa isso.

    import java.awt.Dimension;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    
    import com.towel.swing.img.JImagePanel;
    
    public class JImagePanelSingleTest {
    	public static void main(String[] args) throws Throwable {
    		JImagePanel panel = new JImagePanel(
    				loadImage("/home/marcos/imgs/1.png"));
    
    		JFrame frame = new JFrame();
    		frame.setPreferredSize(new Dimension(100, 100));
    		frame.add(panel);
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setVisible(true);
    	}
    
    	private static BufferedImage loadImage(String file) throws IOException {
    		return ImageIO.read(new File(file));
    	}
    }
    

    Com isso, temos um resultado como esse:

    Se não quisermos que aumente nossa imagem, podemos usar o FillType como no seguinte código.

    public class JImagePanelSingleTest {
    	public static void main(String[] args) throws Throwable {
    		JImagePanel panel = new JImagePanel(
    				loadImage("/home/marcos/imgs/1.png"));
    
    		panel.setFillType(JImagePanel.FillType.CENTER);
    
    		JFrame frame = new JFrame();
    		frame.setPreferredSize(new Dimension(100, 100));
    		frame.add(panel);
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setVisible(true);
    	}
    
    	private static BufferedImage loadImage(String file) throws IOException {
    		return ImageIO.read(new File(file));
    	}
    }
    

    Com isso temos o seguinte resultado:

    Para utilizar o modo em loop, basta usar o construtor que recebe um long e um array de imagens, o primeiro parametro é o tempo que levará para mudar entre uma imagem e outra em millisegundos.
    Assim que criado uma Thread é disparada para atualizar as imagens, essa Thread é daemon e não vai interferir caso a Thread principal termine.
    Também é possivel utilizar o FillType em modo de loop.

    O código é praticamente o mesmo, ficando assim:

    public class JImagePanelLoopTest {
    	public static void main(String[] args) throws Throwable {
    		JImagePanel panel = new JImagePanel(10, new BufferedImage[] {
    				loadImage("/home/marcos/imgs/1.png"),
    				loadImage("/home/marcos/imgs/2.png"),
    				loadImage("/home/marcos/imgs/3.png"),
    				loadImage("/home/marcos/imgs/4.png"),
    				loadImage("/home/marcos/imgs/5.png"),
    				loadImage("/home/marcos/imgs/6.png"),
    				loadImage("/home/marcos/imgs/7.png"),
    				loadImage("/home/marcos/imgs/8.png"),
    				loadImage("/home/marcos/imgs/9.png"),
    				loadImage("/home/marcos/imgs/10.png"),
    				loadImage("/home/marcos/imgs/11.png"),
    				loadImage("/home/marcos/imgs/12.png") });
    
    		JFrame frame = new JFrame();
    		frame.setPreferredSize(new Dimension(100, 100));
    		frame.add(panel);
    		frame.setLocationRelativeTo(null);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setVisible(true);
    	}
    
    	private static BufferedImage loadImage(String file) throws IOException {
    		return ImageIO.read(new File(file));
    	}
    }
    

    O resultado da execução é uma animação, então não é possivel colocar uma imagem aqui.

    Ainda a fazer nessa classe é o seguinte:

    • Começar a animação com um método start() por exemplo
    • Oferecer um modo para executar a animação apenas uma vez e parar em alguma imagem.




    Towel v1.1

    9 02 2011

    Changelog da versão 1.1 do Towel.

    Pastas de imagens do TableFilter incluida.

    JImagePanel agora tem suporte para exibir uma sequencia de imagens e o ImageLoopPanel que havia antigamente foi depreciado.
    Artigo sobre como usar ele adicionado 11/02/2011, veja aqui.

    Felipe Priuli fez uma contribuição no projeto adicionando mais uma classe util, a DynamicFormatter, ela é um Formatter genérico que foi feita para facilitar o uso do ObjectComboBoxModel, mas ela é genérica e serve para qualquer caso que precise de um Formatter.

    Algo que eu planejava a algum tempo é oferecer um modo onde seja possivel ter colunas em uma JTable com valores agregados como, soma, média, menor, maior e etc.., foi com essa intenção que criei as AggregateFunctions. O model que faz isso para as colunas está pronto, e é o AggregateModel.
    Mas encontrei alguns desafios não triviais para fazer isso funcionar: Não existe nem na JTable nem no JScrollPane um modo de adicionar um footer, criei o componente JTableView, com ele é possivel utilizar esse novo recurso, mas ainda tem alguns defeitos que ainda não consegui resolver (uma contribuição se alguem souber é bem vinda :) ).

    Existe um novo pacote agora, com.towel.sound, ele contém classes para audio que foi migrada do JGF (Java Game Framework) um projeto que o ViniGodoy começou, que agora será descontinuado por que o Alegria irá realizar tudo que ele faz e mais ainda.

    Desenvolvido pelo ViniGodoy agora foi migrada para o projeto a classe HashBuilder, ela serve para calcular o hash dos objetos facilmente.

    Outro colaborador dessa versão é o Eric Yuzo que melhorou o ObjectTableModel, agora contém mais comentários e também foi alterado para utilizar o fireTableCellChanged no lugar de fireTableDataChanged que eu estava usando anteriormente.

    ObjectTableModel agora implementa Iterable, então é possivel percorrer a lista dos dados com o for-each.

    Alguém que ajudou bastante comentando muitas classes foi o Marco A. Biscaro (marcobiscaro do GUJ), graças a ele e outras contribuições agora o Java Doc está quase completo.

    Em breve vou gerar o Java Doc e hospedar em algum lugar, mas por enquanto já é possivel navegar pelas classes e ler os docs nas proprias classes.

    Estarei publicando os artigos desses recursos em pouco tempo.

    A pagina Towel Project foi expandida, vale a pena dar uma olhada e baixar a nova versão.





    Towel v1.0!

    13 12 2010

    Bem, agora com o projeto com um novo nome(veja motivo aqui).

    Estou lançando a nova versão sob este novo nome, e como novidades temos o seguinte:

    1° Todos os packages foram renomeados de mark.utils. para com.towel.
    2° Foi adicionado a classe TableFilter(Auto-Filtro) criado pelo ViniGodoy no package com.towel.swing.table.
    3° Foi adicionado a classe JImagePanel criado pelo ViniGodoy no package com.towel.swing.img.

    Em breve escreverei um artigo sobre isso.

    E é isso, acessem a página Towel Project para ver como baixar a versão atualizada do projeto.





    MarkUtils renamed!

    9 12 2010

    Bem, a um pequeno tempo, esse nome levemente ego-centrico(diga-se de passagem e sem comentários) do meu projeto não me agrada muito.
    Mas por falta de opções deixei por isso mesmo, até que então, me veio um nome melhor para ele.

    Após consultar o publico (em fato, umas 6 pessoas) e ver que a idéia realmente não é ruim, decedi agora mudar o nome do projeto.

    Inspirado pela obra de Douglas Adams, autor da série The Hitchhiker’s Guide to The Galaxy, decedi finalmente mudar o nome para: “Towel”, é, toalha mesmo, e por que não? O que é mais util do que uma toalha?

    O Guia do Mochileiro das Galaxias faz algumas afirmações a respeito de toalhas.

    “Segundo ele, a toalha é um dos objetos mais úteis para um mochileiro interestelar. Em parte devido a seu valor prático: você pode usar a toalha como agasalho quando atravessar as frias luas de Beta de Jagla; pode deitar-se sobre ela nas reluzentes praias de areia marmórea de Santragino V; pode dormir debaixo dela sob as estrelas que brilham no mundo desértico de Kakrafoon; pode umedece-la e utiliza-la para lutar em um combate corpo a corpo; enrola-la em torno da cabeça para proteger-se de emanações tóxicas ou para evitar o olhar da Terrível Besta Voraz de Traal (um animal estonteantemente burro, que acha que, se você não pode vê-lo, ele também não pode ver você); você pode agitar a toalha em situações de emergência para pedir socorro; e, naturalmente, pode usa-la para enxugar-se com ela se ainda estiver razoavelmente limpa.
    Porém o mais importante é o imenso valor psicológico da toalha. Por algum motivo, quando um strag ( não-mochileiro ) descobre que um mochileiro tem uma toalha, ele automaticamente conclui que ele tem também escova de dentes, esponja, sabonete, lata de biscoitos, garrafinha de aguardente, bússola, mapa, barbante, repelente, capa de chuva, traje espacial, etc, etc. Além disso, o strag terá prazer em emprestar ao mochileiro qualquer um desses objetos, ou muitos outros, que o mochileiro por acaso tenha “acidentalmente perdido”. O que o strag vai pensar é que, se um sujeito é capaz de rodar por toda a Galáxia, acampar, pedir carona, lutar contra terríveis obstáculos, dar a volta por cima e ainda assim saber onde está sua toalha, esse sujeito claramente merece respeito.”

    Veja a versão 1.0 disponivel para download já com novidades.

    Se for encontrado algo com mark.utils é que deve ter passado despercebido, por favor me avisem.

    Cya!





    CollectionsUtil

    13 11 2010

    Nova versão do projeto disponivel para download(ver pagina Towel Project), os tutoriais explicados aqui também estão na Wiki do projeto.

    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;
    	}
    
    }
    

    Se alguém criar uma AggregateFunction interessante e quiser coloca-la no projeto é só me enviar.








    Seguir

    Obtenha todo post novo entregue na sua caixa de entrada.

    Junte-se a 150 outros seguidores