Rve
Rve

Reputation: 117

Java searching array with for loop doesn't find all results

I'm using Java to build an Android application, and I'm trying to build a search function to find a result from a listview. So far, I've managed to get my search function to work, but it doesn't work properly - it only manages to find certain criteria. For example, it finds TC Product name, JC Product name but doesn't find Product name. And if I try to find certain string values, it doesn't seem to find all values either.

Here's my code:

package com.example.user.sortiment;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

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

/**
 * Created by user on 11.05.2018
 */

public class SortimentAdapter extends BaseAdapter {

LayoutInflater mInflator;
List<Sortiment> map;
List<Sortiment> filterMap;

    public void performFiltering(CharSequence constraint) {

        String filterString = constraint.toString().toLowerCase();
        if (Objects.equals(filterString, "")) {
            filterMap = map;
            notifyDataSetChanged();
            return;
        }

        int count = map.size();
        filterMap = new ArrayList<Sortiment>(count);

        Sortiment filterableSortiment ;

        for (int i = 0; i < count; i++) {
            filterableSortiment = map.get(i);
            if 
(filterableSortiment.name.toLowerCase().contains(filterString)) {
                filterMap.add(filterableSortiment);
            }
        }

        notifyDataSetChanged();

    }

public SortimentAdapter(Context c, List<Sortiment> inputMap) {
    mInflator = (LayoutInflater) 
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    map = inputMap;
    filterMap = inputMap;
}

@Override
public int getCount() {
    return filterMap.size();
}

@Override
public Object getItem(int position) {
    return filterMap.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = mInflator.inflate(R.layout.item_layout,null);
    TextView nameTextView = (TextView) v.findViewById(R.id.nameTextView);
    TextView priceTextView = (TextView) v.findViewById(R.id.priceTextView);

    Sortiment viewObject = filterMap.get(position);
    nameTextView.setText(viewObject.name);
    //priceTextView.setText(String.format("%.0f", prices.get(position)));
    priceTextView.setText(viewObject.ean.toString());

    return v;
}

}

I'm suspecting an issue in: if (filterableSortiment.name.toLowerCase().contains(filterString)) { , but im not entirely sure.

Any ideas? Thanks

Upvotes: 1

Views: 126

Answers (4)

Rve
Rve

Reputation: 117

The answer lied in Android Manifest:

android:windowSoftInputMode="stateHidden"

... had to be replaced with:

android:windowSoftInputMode="adjustPan"

Upvotes: 0

Th2mas
Th2mas

Reputation: 11

If you just want to filter your entries in your Sortiment list, I would recommend the Java 8 Stream API. This will filter all your entries in 'map' and save the result in 'filterMap'.

import java.util.List;
import java.util.stream.Collectors;

public void performFiltering(CharSequence constraint) {
    String filterString = constraint.toString().toLowerCase();

    // Define what to do, if filterString is an empty String
    if(filterString.isEmpty()){
        filterMap = map;
        notifyDataSetChanged();
        return;
    }

    // Filter through the sortiment list
    filterMap = map.stream()
        .filter(s -> s.name.toLowerCase().contains(filterString))
        .collect(Collectors.toList());

    notifyDataSetChanged();
}

Upvotes: 1

JohanLarsson
JohanLarsson

Reputation: 195

Now you have updated your answer and it is clear that your "maps" are not maps at all. Hence this is invalidated now. In the future, supply enough information so that your questions can be answered.

public void performFiltering(CharSequence constraint) {

    String filterString = constraint.toString().toLowerCase();
    if (filterString.equals("")) {
        filterMap = map;
        notifyDataSetChanged();
        return;
    }

    int count = map.size();
    filterMap = new ArrayList<Sortiment>(count);

    Sortiment filterableSortiment ;

    for (filterMap.Entry<String, String> entry : filterMap.entrySet())
    {
        filterableSortiment = entry.getValue();
        if (filterableSortiment.name.toLowerCase().contains(filterString)) {
            filterMap.add(filterableSortiment);
        }
    }
    notifyDataSetChanged();
}

Upvotes: 1

Loop
Loop

Reputation: 237

Edit:

Now that the full code has been posted, the map seems to be a list. My below explanations shouldn't apply to your example, apart from some general info on how maps work.

 

Maps, how do they work?

You are doing a for over a map, where the keys might not be in order necessarily.

Here is an explanation of how a map works.

A map is a key-value pair dictionary, not a simple list/array as you mentioned in your title.

This is my assumption, and I might be wrong, but something that looks weird to me is this line:

filterableSortiment = map.get(i);

This one gets via the key i, and not by the i'th position in the list, because a map is not a list.

A map in the mathematical sense is defined as: "A mapping of elements from one set to another."

Pay attention if the mapping is linear like an array, if not you might not reach all your elements.

 

The core issue:

The map you are using probably doesn't have linear keys and cannot be accessed by a simple increasing i for loop.

Check the structure of your map, by inspecting it at debug.

If your key-value pairs don't look like an array:

0 1 2 3 4 5

| | | | | |

A B C D E F

Then your algorithm will miss elements.

For example if in the map some elements have been added with the key 2324, when your count is just 30 elements, you will miss that since your map is sparsely populated through its keys.

If your map looks like

1 5 7 8 9 23

| | | | | |

A B C D E F

If you do a for 0 > map.count

You will go

map.get(0) - returns nothing

map.get(1) - returns A

map.get(2) - returns nothing

map.get(3) - returns nothing

map.get(4) - returns nothing

map.get(5) - returns B

The C, D, E and F elements are missed out with this approach, if the keys are not in order like in an array "map".

 

The solution:

I would suggest using an appropriate iterator (for each loop) on your map, instead of using a for loop that has a linearly increasing index i since you might miss the gaps in the map.

Refer to this answer or this answer

 

Follow-up questions:

  • Can you mention what data type the map is in your example?

filterMap = map;

Upvotes: 1

Related Questions