Reputation: 348
I need to filter an ArrayList each time that user input a string in a textbox or/and click a button to add boolean attribute to filters.
public class ItemULD {
private int idULD;
private String contour;
private String numULD;
private boolean withNet;
}
And I tried with this method to filter the string in textbox
List<Integer> ids = grupoChip.getCheckedChipIds();
for (Integer id : ids) {
Chip chip = grupoChip.findViewById(id);
ArrayList<ItemULD> arrayFiltered; = new ArrayList<>();
for (ItemULD uld : arrayULD) {
String num = String.valueOf(uld.getNumULD());
if (num.contains(chip.getText()) || uld.getContour().contains(chip.getText())) {
if (!arrayFiltered.contains(uld))
arrayFiltered.add(uld);
}
}
//Method to filter ULD's with net
public static List<ItemULD> filters(List<ItemULD> allULD, boolean net){
List<ItemULD> list = new ArrayList<>();
for (ItemULD uld : allULD) {
if (!net || uld.iswithNet()) {
list.add(uld);
}
}
return list;
}
The problem is when I try to add a new filter on the filtered results that didn't works.. E.G. I have this.
idULD:1,
contour:EK,
numULD: 123456,
withNet:1
idULD:2,
contour:AF,
numULD: 652466,
withNet:0
idULD:3,
contour:AF,
numULD: 123663,
withNet:0
If I put on my seach textbox 123
I see 2 results id1 & id3 this is ok, but when I add AF
I see two AF not only the match AF + 123
that would be the id3.
On the other hand, if I click the option to filter by attribute withNet
I see all the results. I guess this is caused because I'm creating a new array in the method to return but, how I could do it?
EDIT
I use a ChipGroup to add Chip elements with the string that user write in a textbox. Then I iterate the ChipGroud to get the text of every Chip. So if the user write "123" + Enter a new Chip is added to the group
Upvotes: 0
Views: 461
Reputation: 286
An extendable way of solving this is creating an interface Filter
,
something like this:
interface Filter{
// This method checks if the filter is applied for the provided itemText.
// For example, if the filter is a numULD filter, it returns true
// iff the itemText is a number.
boolean isApplicableTo(String itemText);
// This method applies the filter. It returns true if the resulting list
// shall contain the item, and false if the item shall not appear in the
// list. For example, for the contour filter, the return value of the method is
// item.getContour().contains(itemText)
boolean applyTo(ItemULD item, String itemText);
}
Now create three classes implementing this interface, one for contour
, one for numULD
, and one for withNet
. Create instances of these classes and put them in a collection. Iterate over the collection and check if the filter is applicable and if yes, apply the filter. And then perform an and operation (&&
) on the result, starting with a variable boolean result = true;
If you've done that, you could even move this method to its own class Filters
that takes several filters as arguments and returns the filtered result list.
EDIT: Here's a code example.
This is a test class that checks that the filter works correctly:
class FiltersTest {
@Test
void testsFilters() {
Filter contourFilter = new ContourFilter();
Filter numFilter = new NumFilter();
Filters filters = new Filters(contourFilter, numFilter);
ItemULD item1 = new ItemULD(1, "EK", "123456", true);
ItemULD item2 = new ItemULD(2, "AF", "652466", false);
ItemULD item3 = new ItemULD(3, "AF", "123663", false);
List<ItemULD> items = Arrays.asList(item1, item2, item3);
List<Chip> chips = Arrays.asList(new Chip("AF"), new Chip("123"));
assertEquals(Arrays.asList(item3), filters.applyToItems(items, chips));
}
}
These are the filter classes, based on the filter interface shown above:
class ContourFilter implements Filter{
@Override
public boolean isApplicableTo(String itemText) {
// Place your RegEx check here
}
@Override
public boolean applyTo(ItemULD item, String itemText) {
String contour = item.getContour();
return contour.contains(itemText);
}
}
class NumFilter implements Filter{
@Override
public boolean isApplicableTo(String itemText) {
if (itemText == null) {
return false;
}
try {
Integer.parseInt(itemText);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
@Override
public boolean applyTo(ItemULD item, String itemText) {
String num = String.valueOf(item.getNumULD());
return num.contains(itemText);
}
}
The filters class could look like this:
class Filters{
private final List<Filter> filtersList;
public Filters(Filter... filters) {
this.filtersList = Arrays.asList(filters);
}
public List<ItemULD> applyToItems(List<ItemULD> items, List<Chip> chips) {
List<ItemULD> filteredItems = new ArrayList<>();
for (ItemULD item : items) {
if(applyToItem(item, chips)) {
filteredItems.add(item);
}
}
return filteredItems;
}
public boolean applyToItem(ItemULD item, List<Chip> chips) {
boolean result = true;
for (Chip chip : chips) {
String chipText = chip.getText();
for (Filter filter : filtersList) {
if(filter.isApplicableTo(chipText)) {
result = result && filter.applyTo(item, chipText);
}
}
}
return result;
}
}
The Chip
class is only a simplified version:
class Chip{
private final String text;
public Chip(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
Upvotes: 1