Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Java - ArrayList - Stream - Jak přefiltrovat pouze čísla a String?

Dobrý den,

public ArrayList<String> getAllFields() {
      return Arrays.stream(getClass().getDeclaredFields())
                  .filter(field -> !Modifier.isStatic(field.getModifiers()))
                  .map(this::getFieldValue)
                  .filter(field -> !field.equals("null"))
                  .collect(Collectors.toCollection(ArrayList::new));
}

private String getFieldValue(final Field field) {
      try {
           return Objects.toString(field.get(this));
      } catch (final IllegalAccessException e) {
           throw new RuntimeException(e);
      }
}

Potřebuji, aby filtroval pouze celá čísla a řetězce.

Jak to, prosím Vás, musím upravit?

Děkuji

loading...
Předmět Autor Datum
Ahoj, v Javě nedělám, co toto? Na následujícím odkaze můžeš předat filtru složitější podmínku, kte…
Flash_Gordon 23.05.2019 17:30
Flash_Gordon
Díky. O tomhle jsem nevěděl, ale udělal jsem to jiným způsobem. Když použiji kód v předešlé otázce… nový
MichalDM 26.05.2019 00:08
MichalDM
string.matches("-?\\d+") nový
MaSo 26.05.2019 08:06
MaSo
Použít regulární výrazy. To mě nenapadlo. Jenže, tohle lze použít u řetězce. U něho však nelze zjis… nový
MichalDM 27.05.2019 00:50
MichalDM
Tak jsem to upravil do téhle podoby. public ArrayList<String> getAllFields() { return Arrays.stream… poslední
MichalDM 31.05.2019 23:33
MichalDM

Ahoj,

v Javě nedělám, co toto?

Na následujícím odkaze můžeš předat filtru složitější podmínku, kterou definuješ dříve:
https://howtodoinjava.com/java8/java-stream-filter-example/

najdi odstavec:
3.2. Find all even numbers – Predicate class

 
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
         
        Predicate<Integer> condition = new Predicate<Integer>()
        {
            @Override
            public boolean test(Integer n) {
                if (n % 2 == 0) {
                    return true;
                }
                return false;
            }
        };
 
        list.stream().filter(condition).forEach(System.out::println);

Podobně můžeš definovat podmínky pro tvůj ArrayList a tam testovat.

Zda lze převést string na číslo, zda následné číslo je desetinné.

Ale pozor, asi to nebude nijak rychlé. Tudíž ne moc vhodné na velké seznamy.

Díky. O tomhle jsem nevěděl, ale udělal jsem to jiným způsobem.

Když použiji kód v předešlé otázce

public ArrayList<String> getAllFields() {
               return Arrays.stream(getClass().getDeclaredFields())
                           .filter(field -> !Modifier.isStatic(field.getModifiers()))
                           .map(this::getFieldValue)
                           .filter(Objects::nonNull)
                           .map(Objects::toString)
                           .collect(Collectors.toCollection(ArrayList::new));
}

private Object getFieldValue(final Field field) {
      try {
            return field.get(this);
      } catch (final IllegalAccessException e) {
            throw new RuntimeException(e);
      }
}

Tak změním

.filter(Objects::nonNull)

na

.filter(object -> Objects.nonNull(object) && (object instanceof String || object instanceof Integer))

Ale, nejsem si jistý, jestli je tohle nejlepší způsob. Co myslíte Vy?

Navíc, nechci se odkazovat pouze na Integer. Nevíte, jak se odkazovat na celá čísla, bez nutnosti vypisovat všechny použitelné datové typy? Pokud je to vůbec možné.

Prosím o radu.

Děkuji

Použít regulární výrazy. To mě nenapadlo.

Jenže, tohle lze použít u řetězce. U něho však nelze zjistit, jestli byl původně String. A to je ten problém.

Díky tomu není možné použít druhý filtr pouze pro nonnull a přidat třetí filtr za mapování na řetězec.

Odfiltrovat String, ještě před mapováním na řetězec, taky nelze. Nelze mu říct, že nesmí být null, ale "může" být String. A i kdyby to šlo, třetí filtr by stejně bral, že to není číslo a vyhodil ven.

Jediné řešení, které mě napadlo, je

.filter(object -> Objects.nonNull(object) && (object instanceof String || object.toString().matches("-?\\d+")))

Jenže, NetBeans hlásí WARNING NullPointer Dereference a musím to dvakrát převést na řetězec, což není vůbec optimální.

Jak by jste to, prosím Vás, nejlépe upravil?

Díky

Tak jsem to upravil do téhle podoby.

public ArrayList<String> getAllFields() {
        return Arrays.stream(getClass().getDeclaredFields())
                .filter(field -> !Modifier.isStatic(field.getModifiers()))
                .map(this::getFieldValue)
                .filter(Objects::nonNull)
                .map(Objects::toString)
                .filter(field -> field.matches("-?\\d+") || isName(field))
                .collect(Collectors.toCollection(ArrayList::new));
    }

    private Object getFieldValue(final Field field) {
        try {
            return field.get(this);
        } catch (final IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    
    private boolean isName(String field) {
        return field.equals(name); - name je název fieldu třídy
    }

Teď to dělá přesně, co chci. Ale chtěl jsem ještě jednu úpravu.

Tu bych ale dal do samostatné otázky. - odkaz

Každopádně díky za matches.

Zpět do poradny Odpovědět na původní otázku Nahoru

loading...