Problem początkującego z metodami generycznymi

0

Witam

Mam problem ze zmianą poniższych metod na metody generyczne. Prosiłbym o wskazówki jak to zrobić?


public void replaceThird(ArrayList<E> list, E element) {
        list.set(2, element);
    }

    public void increaseSize(ArrayList<E> list, int size) {
        list.ensureCapacity(list.size() + size);
    }

    public void trimSize(ArrayList<E> list) {
        list.trimToSize();
    }

    public void clearList(ArrayList<E> list) {
        list.clear();
    }
4

Jaki masz błąd kompilacji? Wpisz w Google „Java generics methods”. Dawno nie kodowalem, ale spróbuj coś w stylu <T> void metoda(List<T> lista)

0

Spojrzałem na dokumetację i zmieniłem dwie pierwsze metody. Czy tak to ma wyglądać?? Ktoś mógłby mi to łopatologicznie wyjaśnić;D??


public <T> void replaceThird(ArrayList<T> list, T element) {
        list.set(2, element);
    }

    public <T> void ensure(ArrayList<T> list, int value){
        list.ensureCapacity(value);
    }

1

Ale działa czy nie działa?

3
MalarzAr napisał(a):

Ktoś mógłby mi to łopatologicznie wyjaśnić;D??

Polecam (sam przerabiałem) wykłady tego pana: Rob Edwards CS310, Data Structures in Java at San Diego State University.

Playlist:

Będziesz mieć dobrze wytłumaczone. Od podstaw Java przez listy, bardzo przystępne wykłady.

0

Generyczna metoda bez generycznej deklaracji klasy?

Pokaż pełny kod.

0

Problem jest w

    public void increaseSize(ArrayList<E> list, int size) {
        list.ensureCapacity(list.size() + size);
    }

    public void trimSize(ArrayList<E> list) {
        list.trimToSize();
    }

Bo jakby dać poprawnie, jak chce @AnyKtokolwiek to nie ArrayList a List, w List nie ma metod ani ensureCapacity ani trimToSize (bo np dla implementacji LinkedList nie mają sensu)

Dlatego polecam jakiś dobry kurs "od podstaw".

1

Po kolei:

  1. Możesz oznaczyć typ generyczny jako dowolny:
    /**
     * Nie obchodzi nas jakiego typu to lista - dlatego korzystamy z <?>
     */
    public static void withWildCard(final List<?> list, final List<?> secondList) {
        System.out.println(list.size() + secondList.size());
    }

    public static void test() {
        List<String> stringList = new ArrayList<>();
        List<Integer> integerList = new ArrayList<>();

        // Obie wersje zadziałają - nie ma żadnych wymagań co do typu
        withWildCard(stringList, integerList);
    }
  1. Chcesz, żeby argumenty były zgodnego typu:
/**
     * Chcemy zapewnić zgodność typu listy z przekazywanym elementem - przed void deklarujemy, że istnieje typ: <T>
     * Potem zapisujemy, że List musi być <T>, oraz podany obiekt musi być tego samego typu
     */
    public static <T> void withAnyType(final List<T> list, T element) {
        list.add(element);
    }

    public static void test() {
        List<String> stringList = new ArrayList<>();

        withAnyType(stringList, 1); // nie zadziała bo stringList ma typ <String>, a 1 jest typu Integer
        withAnyType(stringList, "1"); // to już zadziała bo stringList i "1" są tego samego typu
    }
  1. Chcesz, żeby argumenty były konkretnego typu - tutaj implementowały Comparable:
    /**
     * Chcemy zapewnić, że typ będzie np. implementował interfejs - przed "void" dorzucamy <T extends Comparable<T>>
     */
    public static <T extends Comparable<T>> void withComparableType(final T first, final T second) {
        System.out.println("Compare: " + first.compareTo(second));
    }

    public static void test() {
        Object nonComparableObject1 = new Object();
        Object nonComparableObject2 = new Object();
        withComparableType(nonComparableObject1, nonComparableObject2); // nie zadziała bo typ Object nie implementuje Comparable<Object>

        Integer comparableObject1 = 1;
        Integer comparableObject2 = 2;
        withComparableType(comparableObject1, comparableObject2); // zadziała bo Integer implementuje Comparable<Integer>

        String anotherComparableObject1 = "1";
        String anotherComparableObject2 = "2";
        withComparableType(anotherComparableObject1, anotherComparableObject2); // zadziała bo String implementuje Comparable<String>

        withComparableType(comparableObject1, anotherComparableObject1); // nie zadziała - obiekty są innego typu
    }
1

Prosty przykład

kod

import java.util.ArrayList;
import java.util.List;

public class Hat<E> {

    private final List<E> items = new ArrayList<>();

    public void putIn(E item) {

        items.add(item);
    }

    public boolean takeOut(E item) {

        return items.remove(item);
    }

    public boolean isHatEmpty() {

        return items.isEmpty();
    }
}

test

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

public class HatTest {

    private Hat<String> hat;
    private String rabbit;

    @Before
    public void setUp() {

        hat = new Hat<>();
        rabbit = "white rabbit";
    }

    @Test
    public void shouldBeEmptyAtTheBeginning() {

        assertThat(hat.isHatEmpty(), is(true));
    }

    @Test
    public void shouldBeAbleToTakeTheRabbitOutOfTheHat() {

        hat.putIn(rabbit);
        assertThat(hat.isHatEmpty(), is(false));

        final boolean magicTrick = hat.takeOut(rabbit);
        assertThat(magicTrick, is(true));
        assertThat(hat.isHatEmpty(), is(true));
    }
}

Uwaga do kodu i interfejsów

    public void putIn(E item) {

        items.add(item);
    }

metoda add() zwraca boolean
https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#method.summary
bo
Interface Collection<E>
może mieć implementację Set i wtedy ma znaczenie, czy element do Set został dodany czy nie
albo list, wtedy nie ma znaczenia, bo List nie ma własności unique, ale ponieważ to interfejs, więc implementacja musi się trzymać definicji, dlatego dla List zwraca zawsze true (choć to masło maślane).
W przykładzie z królikiem z kapelusza nie muszę zwracać boolean, mogę w putIn zwrócić void. To moja decyzja i moje użycie klasy ArrayList opakowanej w klasę Hat.

2

To jeszcze dla pełniejszego obrazu możesz doczytać o kowariancji i kontrawariancji typów.

https://docs.scala-lang.org/tour/variances.html

1

Jak ktoś bardzo chce albo musi (bo ma Java 1.3) to https://www.amazon.com/Java-Generics-Collections-Development-Process/dp/0596527756
Nawet lagacy code dokładnie poruszone

Przystępnie napisana pozycja

0

Dzięki Panowie za materiały i wskazówki. Będę działać

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