Category Archives: Utilitários

BigDecimal – Resolvendo o Erro: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

E ai pessoal, beleza?

Me deparei com esse erro ao trabalhar com BigDecimal, e no meu caso,
como eu estou trabalhando com $$$ não é sempre uma boa fazer arredondamentos
no meio dos cálculos… podem resultar em alguns reais de diferença…

Erro no seguinte código:

BigDecimal a = newBigDecimal("1.6");
BigDecimal b = newBigDecimal("9.2");
a.divide(b);

Para resolver o erro apenas arredondando, faça da seguinte forma:

BigDecimal a = newBigDecimal("1.6");
BigDecimal b = newBigDecimal("9.2");
a.divide(b, 2, RoundingMode.HALF_UP);

Onde o “2”, é o número de cadas após o ponto… e o RoundingMode é o modo de arredondamento (existem diversos)!

Para resolver o erro SEM arredondar, faça da seguinte forma:

BigDecimal a = newBigDecimal("1.6");
BigDecimal b = newBigDecimal("9.2");
a.divide(b, MathContext.DECIMAL128);

Você pode escolher o número de bits que você quer entre 32, 64 ou 128…

Bom é isso ai pessoal… abraços!!!

Fonte: StackOverflow – DVK / MindBrain

Anúncios

Ordenando Lista de Objetos em Java

Pessoal, andei apanhando um pouco no trabalho, e achei essa solução, para ordenar um ArrayList,
segue abaixo o que salvou minha vida ahuahuahuaha :

Quem nunca na sua vida de programador, seja iniciando pela linguagem de programação C ou direto pelo Java, não enfrentou alguns problemas com Segmentation fault e NullPointException ao trabalhar-se com vetores, principalmente por se acessar índices que não existiam. Na linguagem de programação C não existe muita escapatória para esses casos, além de implementar toda a lógica para a manipulação desses vetores. Um dos exercícios clássicos em C é o de ordenar um vetor em ordem crescente ou decrescente, utilizando-se de alguma lógica com fors e ifs.

Ao iniciar o estudo em Java, também aprendemos a utilizar primeiramente os vetores e enfrentamos os mesmos problemas que no C, até fazemos os mesmos exercícios já feitos em C sobre vetores. Mas ai pensamos, Java sendo uma linguagem de mais alto nivel que o C, será que não existe uma solução mais elegante? A resposta vem da Collections Framework, que é uma API robusta criada pela Sun que possui diversas classes que representam estruturas de dados avançadas, como ArrayList e LinkedList, e funções úteis para se trabalhar com vetores.

O objetivo desse artigo não é dar toda explicação de como utilizar a sintaxe da API Collections, sendo os dois primeiros parágrafos uma breve introdução sobre o assunto, mas sim de como ordenar uma lista de objetos em Java sem ter que implementar nenhuma lógica mirabolante. Uma lista de objetos em Java pode ser facilmente ordenada utilizando o método sort da API Collections. Como exemplo iremos criar uma lista de strings e adicionar algumas palavras nela, depois iremos imprimir essa lista para ver sua ordem. Depois executaremos o método sort para ordenar a lista e imprimiremos novamente a lista para comparar o resultado.

List<String> lista = new ArrayList<String>();
lista.add("fogo");
 lista.add("agua");
 lista.add("vento");
 lista.add("terra");
for(String i : lista){
 System.out.println(i);
 }
Collections.sort(lista);
 System.out.println("Ordenando a lista:");
for(String i : lista){
 System.out.println(i);
 }

Resultado:

fogo
agua
vento
terra
Ordenando a lista:
agua
fogo
terra
vento

Como pode ser visto acima, a lista foi reordenada em ordem crescente. Mas como o método sort sabia como organizar a lista? Ele precisa utilizar um método int compareTo(Object) para poder ordenar a lista, que retorna zero, se o objeto comparado for igual a este objeto, um número negativo, se este objeto for menor que objeto dado, e um número positivo, se este objeto for maior que o objeto dado. Este método está definido na interface Comparable, que deve ser implementado pela classe que será ordenado em uma lista. Não é necessariamente obrigatório que a classe implemente a interface Comparable, ao chamar o método sort pode também ser passado como parâmetro além da lista que será ordenada um método que fará a ordenação.

Entendemos como à ordenação é feita, mais ainda assim não implementamos a interface Comparable e nenhuma logica para a ordenação. Como a lista pode ser ordenada com o método sort? A resposta é que a classe string já implementa a interface Comparable que ordena em ordem alfabética seus elementos. Outras classes em Java que implementam essa interface são: BigDecimal, BigInteger, Byte, ByteBuffer, Character, CharBuffer, Charset, CollationKey, Date, Double, DoubleBuffer, File, Float, FloatBuffer, IntBuffer, Integer, Long, LongBuffer, ObjectStreamField, Short, ShortBuffer e URI que podem ser ordenadas simplesmente utilizando-se o método sort.

Agora chegamos ao caso se quisermos ordenar uma lista de objetos de uma classe que nós mesmos criamos. Para isso a nossa classe deve implementar a interface Comparable. Utilizaremos como exemplo a classe abaixo chamada carro, que contém apenas dois atributos, cilindrada e cor, e um construtor que recebe esses atributos.

public class Carro {
private String cor;
 private int cilindrada;
public Carro(String cor, int cilindrada) {
 super();
 this.cor = cor;
 this.cilindrada = cilindrada;
 }
public String getCor() {
 return cor;
 }
public void setCor(String cor) {
 this.cor = cor;
 }
public int getCilindrada() {
 return cilindrada;
 }
public void setCilindrada(int cilindrada) {
 this.cilindrada = cilindrada;
 }
 }

Realizaremos agora as modificações necessárias na nossa classe carro para que possamos ordenar uma lista da nossa classe utilizando o método sort. Primeiramente a nossa classe deve implementar a intarface Comparable e consequentemente implementar o método sort, lembrando que este método retorna zero se o objeto é igual, um numero negativo se for menor e um numero positivo se for maior. Iremos também decidir como queremos a ordenação da nossa lista de carros seja feita, a ordenação será feita em ordem decrescente de cilindrada, e em caso de ter igual será ordenado em ordem alfabética de cor. A classe finalizada por ser vista abaixo.

public class Carro implements Comparable {
private String cor;
 private int cilindrada;
public Carro(String cor, int cilindrada) {
 super();
 this.cor = cor;
 this.cilindrada = cilindrada;
 }
public String getCor() {
 return cor;
 }
public void setCor(String cor) {
 this.cor = cor;
 }
public int getCilindrada() {
 return cilindrada;
 }
public void setCilindrada(int cilindrada) {
 this.cilindrada = cilindrada;
 }
public int compareTo(Carro carro) {
 if(this.cilindrada > carro.cilindrada){
 return -1;
 }
 else if(this.cilindrada < carro.cilindrada){
 return 1;
 }
 return this.getCor().compareToIgnoreCase(carro.getCor());
 }
 }

Para mostrar que a ordenação realmente funcionou, iremos fazer um teste, onde criaremos uma lista de carros, adicionaremos alguns carros há lista, alguns com mesma cilindradas e cores diferentes. Depois iremos imprimir essa lista de carros, executar o método sort e exibir de novo a lista para ver se a ordenação realmente ocorreu.

List carros = new ArrayList();
carros.add(new Carro("Azul",500));
 carros.add(new Carro("Verde",300));
 carros.add(new Carro("Laranja",700));
 carros.add(new Carro("Marrom",300));
 carros.add(new Carro("Amarelo",700));
for(Carro c : carros){
 System.out.println("Carro de cor "+c.getCor()+" e "+c.getCilindrada()+" cilindradas.");
 }
Collections.sort(carros);
 System.out.println("Ordenando a lista:");
for(Carro c : carros){
 System.out.println("Carro de cor "+c.getCor()+" e "+c.getCilindrada()+" cilindradas.");
 }

Resultado:

Carro de cor Azul e 500 cilindradas.
 Carro de cor Verde e 300 cilindradas.
 Carro de cor Laranja e 700 cilindradas.
 Carro de cor Marrom e 300 cilindradas.
 Carro de cor Amarelo e 700 cilindradas.
 Ordenando a lista:
 Carro de cor Amarelo e 700 cilindradas.
 Carro de cor Laranja e 700 cilindradas.
 Carro de cor Azul e 500 cilindradas.
 Carro de cor Marrom e 300 cilindradas.
 Carro de cor Verde e 300 cilindradas.

Como esperado a ordenação funcionou corretamente. Era isso que este artigo proponha a se tratar, pode ser algo simples para algumas pessoas, mas para quem não conhece pode ser de grande ajuda, facilitando muito o seu trabalho.

Fonte: blog.sippulse.com – Jonas Diogo

O eterno problema de calcular a diferença de dias entre duas datas em Java

E ai pessoal, beleza? achei um artigo mto legal sobre manipulação de datas!
Segue abaixo 😀

Seu chefe te dá a seguinte missão: calcular a diferença de dias entre duas datas. Usando API do java.util.Date ou java.util.Calendar você até consegue dar um jeito. Um mês depois ele pede a você que calcule novamente essa diferença, mas desprezando sábados e domingos. E agora? O que fazer? E tem mais, um tempo depois ele pede que despreze também os feriados, dias abonados, e dias que não teve expediente (greve, recesso, comemorações), considerando assim apenas os dias úteis. É um problema relativamente corriqueiro, a questão é como solucioná-lo sem fazer malabarismos com as classes do java.util, que deixam bastante a desejar.

Uma solução prática para este problema é o uso do JodaTime, projeto criado justamente para facilitar a manipulação de datas em Java. A biblioteca voltou a figurar nas notícias pois foi anunciado recentemente que a API de Data será reformulada para o Java 8, sob a especificação JSR 310, fortemente inspirada pelo JodaTime, já que um dos spec leaders é o próprio criador.

A especificação já existe há um bom tempo, inclusive conta com a participação do Fábio Kung, que já explicou em 2007 como seria a proposta. Porém, enquanto o Java 8 não chega, para resolvemos o problema, além do JodaTime.

Inicialmente, para obter uma data, basta instanciar um DateTime, que possui uma API bem completa e tem a vantagem de ser imutável. Ela representa um instante no tempo.

DateTime dataInicial = new DateTime(2012, 12, 1, 12, 0);
DateTime dataFinal = new DateTime(2012, 12, 28, 12, 30);
DateTime feriado = new DateTime(2012, 12, 25, 12, 0);

Essa classe funciona muito bem com a API do java.util, possuindo métodos toDate e toCalendar, além de um construtor que pode receber Date e Calendar.

Para calcular quantos dias existem entre uma data e outra, é muito simples:

int dias = Days.daysBetween(dataInicial, dataFinal).getDays();

Days.daysBetween devolve um objeto do tipo Days, que implementa a importante interface Period.

Vamos começar a complicar. Podemos calcular, de maneira análoga, a diferência de horas usando a classe Hours.

System.out.println(
  Hours.hoursBetween(dataInicial, dataFinal).getHours());

Aqui desprezamos os minutos, retornando apenas a quantidade de horas como um valor inteiro. Podemos usar a classe Minutes com BigDecimal.

BigDecimal minutos =
  new BigDecimal(Minutes.minutesBetween(dataInicial, dataFinal).getMinutes());
BigDecimal horas =
  minutos.divide(new BigDecimal("60"), 2, RoundingMode.HALF_UP);
System.out.println(horas); // 648,50h

Caso a gente vá calcular a diferença das datas em diversas unidades de tempo (horas, dias, minutos, etc), podemos utilizar a classe Duration, que tem um construtor que recebe dois instants (como DateTime) e depois permite recuperar a diferença na unidade temporal que você desejar.
Agora temos que descontar os feriados e finais de semana do período. Utilizaremos outras duas bibliotecas, que são relacionadas ao projeto JodaTimeObjectLab Holiday Calculation e Jollyday.

Primeiro passo é descobrir quais são os feriados no Brasil para o ano corrente. Vamos usar o Jollyday, que já vem com algum feriados e você pode customizar outros em um arquivo separado.

HolidayManager gerenciadorDeFeriados =
  HolidayManager.getInstance(de.jollyday.HolidayCalendar.BRAZIL);
Set<Holiday> feriados = gerenciadorDeFeriados.getHolidays(new DateTime().getYear());
Set<LocalDate> dataDosFeriados = new HashSet<LocalDate>();
for (Holiday h : feriados) {
    dataDosFeriados.add(new LocalDate(h.getDate(), ISOChronology.getInstance()));
}

Segundo passo é dado a lista de feriados dataDosFeriados, vamos utilizar o calendário do ObjectLab Holiday Calculation para descobrir se uma determinada data é dia útil, baseado tanto nos feriados quanto nos fins de semana. Fazemos isso através do método isNonWorkingDay

// popula com os feriados brasileiros
HolidayCalendar<LocalDate> calendarioDeFeriados
  = new DefaultHolidayCalendar<LocalDate>(dataDosFeriados);
LocalDateKitCalculatorsFactory.getDefaultInstance()
  .registerHolidays("BR", calendarioDeFeriados);
DateCalculator<LocalDate> calendario =
  LocalDateKitCalculatorsFactory.getDefaultInstance().
    getDateCalculator("BR", HolidayHandlerType.FORWARD);
// true - sábado
calendario.isNonWorkingDay(new LocalDate(dataInicial));
// false
calendario.isNonWorkingDay(new LocalDate(dataFinal));
// true - natal
calendario.isNonWorkingDay(new LocalDate(feriado));

Por fim, agora temos que descobrir quantos dias não úteis existem no período e descontar das horas já calculadas. Vamos caminhando de data em data e perguntando se ela é ou não dia útil. Se não for, incrementamos diasNaoUteis:

int diasNaoUteis = 0;
LocalDate dataInicialTemporaria = new LocalDate(dataInicial);
LocalDate dataFinalTemporaria = new LocalDate(dataFinal);
while (!dataInicialTemporaria.isAfter(dataFinalTemporaria)) {
    if (calendario.isNonWorkingDay(dataInicialTemporaria)) {
       diasNaoUteis++;
    }
    dataInicialTemporaria = dataInicialTemporaria.plusDays(1);
}

Se quisermos calcular o número de horas úteis entre essas datas, basta subtrair o total de horas que já calculamos de 24*diasNaoUteis:

System.out.println("Horas finais líquidas: " +
  horas.subtract(new BigDecimal(24 * diasNaoUteis)));

O código pode ser um pouco mais eficiente. Há uma outra solução para não precisar fazer um loop que passe por todas as datas do nosso intervalo. Podemos chamar HolidayManager.getHolidays() passando o intervalo das nossas datas, recebendo um Set. Invocando o size desse conjunto, temos o número de feriados do intervalo. Também calculamos quantos fins de semana tivemos, utilizando Weeks.weeksIn no nosso intervalo. Por último, precisamos tomar cuidado e verificar quais feriados cairam em fins de semana, para não contá-los duas vezes.

E você, como costuma resolver estes problemas? Vale lembrar que JodaTime possui integração com Hibernate e pode ser facilmente configurada no seu projeto. Também é fundamental pensar nos casos particulares quando escrever seus testes de unidade. É muito fácil você cair em situações estranhas, em especial se sua data possui horas e minutos, além de anos bissextos, feriados que caem em fins de semana, etc.

Fonte: Blog.Caelum – Raphael Lacerda