I'm wanting to compare the strings in an array list taken from my database and join them together..
Here is the code which collects data from my database..
public List<String> getData2List() {
String[] columns = new String[]{ KEY_ROWID, KEY_DATE, KEY_NAME, KEY_PRICE};
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, "1", null, null, null, null);
List<String> results = new ArrayList<String>();
int iCM = c.getColumnIndex(KEY_DATE);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
results.add(c.getString(iCM));
}
return results;
}
and here is the code to place them in the list..
Database info = new Database(this);
info.open();
List<String> dates = info.getData2List();
lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, dates));
info.close();
This all works fine but if there are more than one entry which is the same I end up with a list of the same thing (if this makes sense!?).
Example:
if the list came out like {"01/01/13", "02/01/13", "01/01/13", "03/02/13", "01/01/13"}
I'm trying to make the out come like {"01/01/13", "02/01/13", "03/02/13"}
so that all entry of the same value have been compiled into one.
Any help or ideas is much appreciated.
Just use an Set instead of a List.
An HashSet will provide you unique strings, a List instead can contain same occurrence.
Why don't you just use HashSet<String> ?
Example:
List<String> dates = info.getData2List();
Set<String> uniqueDates = new HashSet<String>(dates);
You can use HashSet instead of ArrayList.
because in your case you will have following advantages
joining two set will be more easier useing addAll method
There is no chance to have duplicate values
You need a Set collection class, basically what "Set" does is, storing only unique values, and if you try to set a new value that already exist in the collection it will just ignore, make sure you are overriding equals, and hashCode method as well in case you are trying to store your own object, look at the documentation for more info about how it works..
http://docs.oracle.com/javase/6/docs/api/java/util/Set.html
Regards!
Related
I have searched for this on stackoverflow and found unrelated threads for this case. I have also tried on my own, and will keep trying until the solution. But it will be good if someone shows me if i am doing any mistakes in code.
I am having a HashSet so that i can keep away duplicate strings from being getting added to it. And if HashSet is adding then it must be a unique string.
My class declarations are :
public List<String> ContactsList;
public List<String> ContactsNumbersList;
My code to fetch contacts and adding it into these two lists by taking help of HashSet so that i keep duplicate numbers away is :
ContactsList = new ArrayList<String>();
ContactsNumbersList = new ArrayList<String>();
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
// Contacts Database queries
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, ContactsContract.CommonDataKinds.Phone.SORT_KEY_PRIMARY +" ASC");
while (cursor.moveToNext())
{
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (normalizedNumbersAlreadyFound.add(phoneNumber))
{
phoneNumber = phoneNumber.replace("-","");
phoneNumber = phoneNumber.replace(" ","");
phoneNumber = phoneNumber.replace("(","");
phoneNumber = phoneNumber.replace(")","");
ContactsList.add(name);
ContactsNumbersList.add(phoneNumber);
}
}
cursor.close();
Well then why my ContactsNumbersList having duplicate entries...? Thanking you in advance for any suggestions.. which will help me.
There seems to be a problem with your design.
First and foremost, you don't need Lists if your goal is to use a collection without duplicates.
Just use your Set instead.
Secondly, and specifically to your code, you are checking whether the element is added to your Set before normalizing it and adding the normalized String to the List.
Therefore, it may very well be that your List will contain duplicates because two elements that differ before normalization may be equal after normalization.
This leads me back to advise you to use your Set directly and disregard using a List in this use case.
Example
List<String> source = Arrays.asList("123-456789", "(1)23456789");
System.out.printf("Source List contains: %s%n", source);
Set<String> set = new HashSet<>();
List<String> unnecessary = new ArrayList<>();
Set<String> useful = new HashSet<>();
for (String s: source) {
if (set.add(s)) System.out.printf("Added %s to set.%n", s);
s = s.replaceAll("[()-]", "");
System.out.printf("\t... now normalized to %s%n", s);
// s is now normalized
unnecessary.add(s);
useful.add(s);
}
System.out.printf(
"Set contains %s.%nUnnecessary List contains %s.%nUseful Set contains %s.%n",
set,
unnecessary,
useful
);
Output
Source List contains: [123-456789, (1)23456789]
Added 123-456789 to set.
... now normalized to 123456789
Added (1)23456789 to set.
... now normalized to 123456789
Set contains [(1)23456789, 123-456789].
Unnecessary List contains [123456789, 123456789].
Useful Set contains [123456789].
I have a HashSet of Strings in the format: something_something_name="value"
Set<String> name= new HashSet<String>();
Farther down in my code I want to check if a String "name" is included in the HashSet. In this little example, if I'm checking to see if "name" is a substring of any of the values in the HashSet, I'd like it to return true.
I know that .contains() won't work since that works using .equals(). Any suggestions on the best way to handle this would be great.
With your existing data structure, the only way is to iterate over all entries checking each one in turn.
If that's not good enough, you'll need a different data structure.
You can build a map (name -> strings) as follows:
Map<String, List<String>> name_2_keys = new HashMap<>();
for (String name : names) {
String[] parts = key.split("_");
List<String> keys = name_2_keys.get(parts[2]);
if (keys == null) {
keys = new ArrayList<>();
}
keys.add(name);
name_2_keys.put(parts[2], keys);
}
Then retrieve all the strings containing the name name:
List<String> keys = name_2_keys.get(name)
You can keep another map where name is the key and something_something_name is the value.
Thus, you would be able to move from name -> something_something_name -> value. If you want a single interface, you can write a wrapper class around these two maps, exposing the functionality you want.
I posted a MapFilter class here a while ago.
You could use it like:
MapFilter<String> something = new MapFilter<String>(yourMap, "something_");
MapFilter<String> something_something = new MapFilter<String>(something, "something_");
You will need to make your container into a Map first.
This would only be worthwhile doing if you look for the substrings many times.
I am trying to learn Java and have come a long way from PHP, I tried to apply the same mentality when creating my code. But as many of you have already known, it doesn't work that easily.
So with that said, I have a question. I want to create a drop down list from items in an ArrayList. I am fond of the idea of using the JOptionPane.showInputDialog() method to attempt this.
This is what I have currently, but I get an error telling me that no suitable method found for showInputDialog
ArrayList<String> projectList = new ArrayList<String>();
while(results.next())
projectList.add(results.getString("project"));
String inputDialog = (String)JOptionPane.showInputDialog(this, "Choose project to open", "Open Project", JOptionPane.PLAIN_MESSAGE, null, projectList, "--");
I know that the issue is that when I pass the ArrayList as the array object I get thrown this error. But if I did something like
Object[] projectList = {"one", "two"};
then it works as intended, I then tried to maybe do this and pass in projects as my array object.
Object[] projects = {projectList.toString()};
This somewhat works, but then the output looked like "one, two" in drop down list as 1 line item.
You can convert ArrayList to Object[] if needed using List.toArray(), ie:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
Object[] result = list.toArray();
projectList is an ArrayList, convert it to array and then pass it to the method JOptionPane.showInputDialog(). Please check List.toArray() method.
String [] projects = projectList.toArray(new String[projectList.size()]);
Try following
Object[] projectListArray =new Object[projectList.size()];
projectList.toArray(projectListArray);
String inputDialog = (String)JOptionPane.showInputDialog(this, "Choose project to open", "Open Project", JOptionPane.PLAIN_MESSAGE, null, projectListArray , "--");
Hope it helps.
Here's what I'm trying to do:
- Retrieve a Map of key-value pairs from a SharedPreferences object (User#, Name)
- write those key-value pairs into an ArrayList such that I can
- use them to populate a ListView with each row containing BOTH the key and the value like so:
User 1 - Joe R.
User 2 - Frank B.
etc
UPDATE:
so after taking a good long look at the SimpleAdapter class, and talking with some wiser more knowledgable folks - I'm a lot closer than I was... but still not all the way there.
here's what I have now:
public class LogHistory extends ListActivity {
static final ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
private static final String KEY = null;
private static final String VALUE = null;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.log_history);
SharedPreferences logPrefs = getSharedPreferences(LoginField.PREFSNAME, 0);
Map<String, ?> logMap = logPrefs.getAll();
for (Map.Entry<String, ?> e : logMap.entrySet()) {
HashMap<String, String> row = new HashMap<String, String>();
String mKey = e.getKey();
String mValue = (String) e.getValue();
row.put(KEY, mKey);
row.put(VALUE, mValue);
list.add(row);
// FOR DEBUGGING PURPOSES
makeToast(mKey);
makeToast(mValue);
}
SimpleAdapter adapter = new SimpleAdapter(
this,
list,
R.layout.list_item,
new String[] { KEY, VALUE },
new int[] {R.id.item1, R.id.item2}
);
setListAdapter(adapter);
This sort of works - but only half way... what I get as a result is a list of the VALUES in both columns...
HOWEVER the makeToast function returns the proper values for both the KEY and the VALUE - so the problem must be in the SimpleAdapter method yes??
assistance would be great - homework is due tonight! :-0
You need to search for "custom listview", "listview custom adapter" and those things. "two line listview item layout"...
See this example. There are others on Google.
Basically, you can create a ArrayList<Hashmap<String,String>>, which is your data container. You add values to that creating as many HashMap<String, String> objects as you need and using list.add(yourHashMap), where list is the ArrayList.
At the end you feed that to a SimpleAdapter (there are other methods, but this works without much trouble).
Check the docs to see how each thing works exactly.
You are nulling your index keys. Put a name into those final Strings.
This sort of works - but only half way... what I get as a result is a list of the VALUES in both columns...
HOWEVER the makeToast function returns the proper values for both the KEY and the VALUE - so the problem must be in the SimpleAdapter method yes??
As I said, no. When you do this:
row.put(KEY, mKey);
row.put(VALUE, mValue);
You are not providing a meaninful difference between KEY and VALUE, because both are null. It's something like putting all things into the same column.
Your mistake into reasoning that is because the Toast test you created yourself test only the correctness of the values, not the columns:
makeToast(mKey);
makeToast(mValue);
In that you test only the values. ;) You assume that the columns are right, and that the mistake could only be in the values, which is exactly the opposite.
First rule of dealing with computers: computers never assume LOL. ;-)
In my SQL database table there are colums _id, int dayofweek, String text ...
I now, do a SQL query on that table to get a cursor to the results.
The results then are shown in a listView:
private void showBlocks()
{
Cursor blocks = ttDB.getBlocks();
startManagingCursor(blocks);
int[] key = new int []{
android.R.id.text1,
android.R.id.text2
};
SimpleCursorAdapter blockAdapter = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_2,
blocks,
new String[] {
"day",
"text"
},
key);
lv1.setAdapter(blockAdapter);
}
How (and where) can I now replace the integer values of dayofweek by the corresponding strings? I thought about joining two tables while querying but then it will not be multilingual any more.
You can try using a ViewBinder via setViewBinder() on your SimpleCursorAdapter.
Or, extend SimpleCursorAdapter, override bindView() and do it yourself.
you can not directly replace values .you have to store first it in list and than you can replace it with ur desired fromat