Inna kopia klucza w mapie

0

Dopiero zaczynam programowanie w Javie i mam zapewne dość trywialne pytanie. Chcę zmapować datę urodzin do grupy osób urodzonych tego dnia:

Map<Date, ArrayList<Person>> dateToPersons;

Jeżeli danej daty urodzenia nie ma jeszcze w mapie, to dodaję wszystkie osoby z taką datą do tejże mapy:

public PersonDatabase(List<Person> myList) {
		this.myList = myList;
		
		dateToPersons = new TreeMap<Date, ArrayList<Person>>();
		
		for(int i = 0 ; i < myList.size() ; ++i)
		{
			if(!dateToPersons.containsKey(myList.get(i).getBirthdate()))
			{
				ArrayList<Person> currentList = new ArrayList<>();
				for(int j = 0 ; j < myList.size() ; ++j)
				{
					if(myList.get(i).getBirthdate().compareTo(myList.get(j).getBirthdate()) == 0)
					{
						currentList.add(myList.get(j));
					}
				}
				dateToPersons.put(myList.get(i).getBirthdate(), currentList);
			}

		}
	}

Problem leży zapewne w tej linijce:

dateToPersons.put(myList.get(i).getBirthdate(), currentList);

Dodaje ona konkretny klucz (object reference) do tej mapy, a kiedy później chcę pobrać grupę osób urodzonych danego dnia:

public List<Person> bornOnDay(Date date) {
	return dateToPersons.get(date);
}

//...

System.out.println("\nPeople born on the 7th sept. 1995:");
for(Person p : myDatabase.bornOnDay(new Date(1995, 9, 7)))
{
	System.out.println(p);
}

(pomijając, że używam konstruktora oznaczonego jako deprecated) to muszę siłą rzeczy stworzyć nowy obiekt typu Date, i dlatego dostaję nullpointer exception. Daty mają takie same wartości ale inne adresy w JVM jak mniemam. Ktoś wie jak temu zaradzić ^^ ?

0

jeżeli trzymasz gdzieś kolekcję tych obiektów Person to możesz za każdym razem w metodzie bornOnDay(Date date)
return persons.stream().filter(p -> p.getDate().equals(date)).collect(Collectors.toList());
to jest feature z javy8.

jeżeli nie chcesz za każdym wywołaniem bornOnDay tego tak przefiltrowywać, bo boisz się o wydajność to możesz mavenem zaciągnąć Guave i użyć np:
SetMultimap<Date,Person> mapa = HashMultimap.create(); jest to takie ala Map<Date,Set<Person>> . inicjujesz to po prostu np:

        for(Person p : persons) {
            mapa.put(p.getDate(),p);
        }

a nie jakimiś kombinacjami alpejskimi

0

Robisz tu panie jakieś cuda na kiju.

for(Person person: mylist)
{
    if(!dateToPersons.containsKey(person.getBirthdate()))
    {
         dateToPersons.put(person.getBirthdate()), new ArrayList<>());
    }
     dateToPersons.get(person.getBirthdate()).add(person);
}

Jeśli już musisz tu tak cudować pętlami. Ja osobiście polecałbym uzyć streamów i collector grouping by ;]
Na przykład tak:

Map<Date, List<Person>> mapped = myList.stream()
        .collect(Collectors.groupingBy(
                        Person::getBirthdate,
                        Collectors.toList()
                )
        );

Edit zaprzeczam jakoby problem był z datami. Coś popsułeś w kodzie. Taki kod działa bez zarzutu:

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Person {
    private final Date birthday;

    Person(Date birthday) {
        this.birthday = birthday;
    }

    public Date getBirthday() {
        return birthday;
    }
}

public class Test {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(new Person(new Date(1,1,1)), new Person(new Date(1,1,1)), new Person(new Date(1,1,2)), new Person(new Date(1,1,2)));
        Map<Date, List<Person>> mapped = persons.stream()
                .collect(Collectors.groupingBy(
                                Person::getBirthday,
                                Collectors.toList()
                        )
                );
        System.out.print(mapped);
    }
}
0

Hmm, usunąłem zbędne części programu i taka dalej rzuca mi null pointer exception:

public final class PersonDatabase {

	List<Person> myList;
	Map<Date, ArrayList<Person>> dateToPersons;
	
	public PersonDatabase(List<Person> myList)
	{
		this.myList = myList;
		dateToPersons = new TreeMap<Date, ArrayList<Person>>();
		
		for(Person person: myList)
		{
		    if(!dateToPersons.containsKey(person.getBirthdate()))
		    {
		         dateToPersons.put(person.getBirthdate(), new ArrayList<>());
		    }
		     dateToPersons.get(person.getBirthdate()).add(person);
		}
	
		for(Person p : dateToPersons.get(new Date(1995, 9, 7)))
		{
			System.out.println(p);
		}
	}

//...
}

A na sto procent są tam osoby z datą urodzenia 7 września 1995...

1

Ale miesiąc w tym konstruktorze jest od 0 do 11 więc 9 to nie wrzesień.

1 użytkowników online, w tym zalogowanych: 0, gości: 1