Olá a todos!
Fiz uma prova um dia desses, que tinha uma questao para sorteiar 500 numeros de 1 à 10, e depois exibir os 5 que mais apareceram, com sua quantidade.
Nao consegui fazê-la. A questao pedia uso de collections… Se alguém puder me ajudar, ficaria grato.
Uma solução possível.
import java.util.*;
class SorteioNumeros {
public static void main(String[] args) {
// Numero sorteado -> contagem de vezes em que o numero foi sorteado
Map<Integer,Integer> frequencia = new HashMap<Integer,Integer>();
// Frequencia do numero sorteado -> numero sorteado
// Como 2 numeros podem ter a mesma frequencia, entao usamos uma lista
SortedMap<Integer,List<Integer>> numerosMaisSorteados = new TreeMap<Integer,List<Integer>>(Collections.reverseOrder());
Random r = new Random();
for (int i = 0; i < 500; ++i) {
Integer numeroSorteado = r.nextInt (10) + 1; // numero de 1 a 10
Integer qtdVezes;
if (!frequencia.containsKey (numeroSorteado)) {
qtdVezes = 1;
} else {
qtdVezes = frequencia.get (numeroSorteado) + 1;
}
frequencia.put (numeroSorteado, qtdVezes);
}
// Agora vamos inverter a lista de frequencias para obter os 5 numeros mais sorteados.
for (Integer numeroSorteado : frequencia.keySet())
{
Integer qtdVezes = frequencia.get (numeroSorteado);
List<Integer> numerosComMesmaFrequencia;
if (numerosMaisSorteados.containsKey (qtdVezes)) {
numerosComMesmaFrequencia = numerosMaisSorteados.get (qtdVezes);
} else {
numerosComMesmaFrequencia = new ArrayList<Integer>();
numerosMaisSorteados.put (qtdVezes, numerosComMesmaFrequencia);
}
numerosComMesmaFrequencia.add (numeroSorteado);
}
// Agora mostrando os 5 numeros mais sorteados...
// Note que se houver numeros empatados em quinto lugar, todos eles serão mostrados.
Iterator<Integer> it = numerosMaisSorteados.keySet().iterator();
for (int i = 0; i < 5; ) {
Integer qtdVezes = it.next();
List<Integer> numeros = numerosMaisSorteados.get (qtdVezes);
for (Integer n : numeros) {
System.out.printf ("O numero %2d foi sorteado %2d vezes%n", n, qtdVezes);
++i;
}
}
}
}
[code]public class Main {
public static void main(String[] args) {
class MapFrequency<K, V> extends HashMap<Integer, Integer>{
public void put(int number) {
int value = 1;
if(containsKey(number)) {
value = get(number) + 1;
}
put(number, value);
}
}
MapFrequency<Integer, Integer> numberFrequency = new MapFrequency<Integer, Integer>();
Random random = new Random();
for(int i = 0; i < 500; i++) {
int randomNumber = 1 + random.nextInt(10);
numberFrequency.put(randomNumber);
}
for(Integer i : numberFrequency.keySet()) {
System.out.print(i + ":" + numberFrequency.get(i) + " ");
}
}
}[/code]
Como é que vcs sabem qual collection usar, quando usar? Eu me enrolei usando HashMap. Tem algum link, com exemplos, que vcs podem indicar para ter eu maior embasamento no uso de Collections??
Valeu a quem respondeu!!
HashMap serve para coleções “desordenadas” e de acesso um pouco rápido.
TreeMap serve para coleções “ordenadas”.
No meu exemplo, eu usei um HashMap (poderia ter usado um Treemap também, é indiferente nesse caso) para contar as freqüências, e um TreeMap para deixar ordenado por freqüência (ou seja, para mostrar os 5 mais freqüentes).
solucao completa
[code]public class Main {
public static void main(String[] args) {
/* mapa incremental */
class MapFrequency<K, V> extends HashMap<Integer, Integer> {
public void put(int number) {
int value = 1;
if(containsKey(number)) {
value = get(number) + 1;
}
put(number, value);
}
}
MapFrequency<Integer, Integer> numberFrequency = new MapFrequency<Integer, Integer>();
/* gerando os numeros */
Random random = new Random();
for(int i = 0; i < 500; i++) {
int randomNumber = 1 + random.nextInt(10);
numberFrequency.put(randomNumber);
}
/* utilizado para ordenacao */
class Peer implements Comparable {
int key;
int value;
public Peer(int k, int v) {
key = k;
value = v;
}
public int compareTo(Object o) {
Peer otherPeer = (Peer) o;
return new Integer(value).compareTo(otherPeer.value);
}
public String toString() {
return key + ":" + value;
}
}
/* gerando pares key/value */
List<Peer> peers = new ArrayList<Peer>(numberFrequency.size());
for(Integer i : numberFrequency.keySet()) {
peers.add(new Peer(i, numberFrequency.get(i)));
}
Collections.sort(peers);
Collections.reverse(peers);
int i = 0;
for(Peer p : peers) {
System.out.println(p);
i++;
if(i == 5) {
break;
}
}
}
}[/code]
[quote=hugalves]Como é que vcs sabem qual collection usar, quando usar? Eu me enrolei usando HashMap. Tem algum link, com exemplos, que vcs podem indicar para ter eu maior embasamento no uso de Collections??
Valeu a quem respondeu!![/quote]
A API de coleções no java ( chamada JCF : Java Collections Framework) é baseada em interfaces.
As interfaces dizem o que vc pode esperar da coleção. São interfaces: List, Set, Map
As implementações dizem com que eficiencia a coleção poderá executar o que se espera dela.
São implementções: ArrayList, LinkedList , LinkedHashSet, HashSet, HashMap, LinkedHashMap, TreeSet, TreeMap
Set = Uma coleção normal. Não aceita duplicados ( ou seja, não consegue colocar o mesmo objeto duas vezes)
List = Pode conter duplicados e os elementos ficam numa ordem associada a indice ( como um array)
Map = Um coleção de pares chave-valor. Vc pode associar o valor a uma chave e obtê-lo usando sómente a chave.
o prefixo Linked indica que a implementação usa cadeias. Isso mantém a ordem de insersão e acelera adições e iterações. contudo diminiu a eficiencia de remoções e procuras.
o prefixo Hash significa que a implementação é baseada na função de hash do objeto. (hashCode())
o profixo Tree signfica que a implementação é baseada na implementação de Comparable ou Comparator.
Hash… é melhor no caso geral, Tree é melhor quando os objetos tem uma ordem intrinseca ( como numeros, datas ou strings)
Eu escrevi algo sobre isso no meu blog