Gwt ListBox Alphabetical Order - java

I have a GWT listbox and i need to sort the contents(Strings) of listbox in alphabetical order.
What is a decent way to solve this?
I was thinking of using a Collection and Sort that or use Arrays.sort() and then populate the listbox with sorted values.Is this a right approach?
Thanks

You have already said the answer and I just code it
Arrays.sort the list
Add items to the list
Here is the code
String[] strings = new String[] { "ab", "ac", "a", "abc" };
java.util.Arrays.sort(strings);
ListBox l = new ListBox();
for (String s : strings) {
l.addItem(s);
}

I made the following method in a helper class:
public static void ListBoxAddSorted(ListBox lb, String text, String value)
{
int count = lb.getItemCount();
int j;
for ( j = 0; j < count; j++ )
{
String item = lb.getItemText( j );
if ( item.compareTo( text ) >= 0 )
{
break;
}
}
lb.insertItem( text, value, j );
}
Basically, as you insert items to the list they are inserted in alphabetical order. This way you can delete and add at will and your list will always be sorted.

Presorting doesn't work when you have many points in the application where things get added to the ListBox. You can add an event handler when it gets updated. Pseudocode:
import com.google.gwt.event.dom.client.ChangeHandler;
ChangeHandler sortMyList(){
//extract your elements, sort, then reinsert
}
ListBox lb = new ListBox();
lb.addChangeHandler( sortMyList());
The other alternative is to extend ListBox to a class called SortedListBox which keeps elements sorted as they are inserted. This would avoid O(n^2) amortized insertion cost.

Related

Sort a list in java into a specific order

What is the best way to implement a custom sort for a List?
I have the List of Constants below.
ENERGY_POLICY, OBJECTIVE, TRAINING, SEU_REPORT, ENERGY_PERFORMANCE, INTERNAL_AND_EXTERNAL_PARTIES, INTERNAL_AUDIT_REVIEW, LEGAL_REQUIREMENTS_REVIEW, TASKS_REVIEW, CORRECTIVE_ACTIONS
I would like to implement a sort function to sort them in the specific order shown below.
[OBJECTIVE, ENERGY_POLICY, TRAINING, ENERGY_PERFORMANCE, INTERNAL_AUDIT_REVIEW, LEGAL_REQUIREMENTS_REVIEW, TASKS_REVIEW, SEU_REPORT, CORRECTIVE_ACTIONS, INTERNAL_AND_EXTERNAL_PARTIES]
Any help pointing me in the right direction would be greatly appreciated.
You can try something like this
List<String> strings = Arrays.asList("OBJECTIVE", "ENERGY_POLICY", "TRAINING", "ENERGY_PERFORMANCE", "INTERNAL_AUDIT_REVIEW", "LEGAL_REQUIREMENTS_REVIEW", "TASKS_REVIEW, SEU_REPORT", "CORRECTIVE_ACTIONS", "INTERNAL_AND_EXTERNAL_PARTIES");
Map<String, Integer> ranks = new HashMap<>();
// Assign rank to each element and store in ranks map. This map will be used for retrieving rank of each element while defining custom sorter
for (int i =0 ; i< strings.size() ; i++) {
ranks.put(strings.get(i),i);
}
// Now lets take a list which needs to sorted based on above order
List<String> stringsToBeSorted = Arrays.asList("ENERGY_POLICY", "OBJECTIVE", "TRAINING", "SEU_REPORT", "ENERGY_PERFORMANCE", "INTERNAL_AND_EXTERNAL_PARTIES", "INTERNAL_AUDIT_REVIEW", "LEGAL_REQUIREMENTS_REVIEW", "TASKS_REVIEW", "CORRECTIVE_ACTIONS");
stringsToBeSorted.sort(new Comparator<String>() {
#Override
public int compare(String str1, String str2) {
if (ranks.get(str1) == null || ranks.get(str2) == null) {
return 0;
}
return ranks.get(str1) - ranks.get(str2);
}
});
Or with Java 8
stringsToBeSorted.sort(Comparator.comparingInt(ranks::get));
But you need to make sure that strings has all the values and there should be no value in stringsToBeSorted list which is not present in strings list. as it will throw null pointer exception as its rank retrieved from hashmap is null
You can put each constant in a hash map with the constant as key and the position as the value.
now as and when you receive the constants get the position it should be from the hashmap and based on it create the final list

Replace strings populated in an ArrayList<String> with other values

I am currently working on a project where I need to check an arraylist for a certain string and if that condition is met, replace it with the new string.
I will only show the relevant code but basically what happened before is a long string is read in, split into groups of three, then those strings populate an array. I need to find and replace those values in the array, and then print them out. Here is the method that populates the arraylist:
private static ArrayList<String> splitText(String text)
{
ArrayList<String> DNAsplit = new ArrayList<String>();
for (int i = 0; i < text.length(); i += 3)
{
DNAsplit.add(text.substring(i, Math.min(i + 3, text.length())));
}
return DNAsplit;
}
How would I search this arraylist for multiple strings (Here's an example aminoAcids = aminoAcids.replaceAll ("TAT", "Y");) and then print the new values out.
Any help is greatly appreciated.
In Java 8
list.replaceAll(s-> s.replace("TAT", "Y"));
There is no such "replace all" method on a list. You need to apply the replacement element-wise; the only difference vs doing this on a single string is that you need to get the value out of the list, and set the new value back into the list:
ListIterator<String> it = DNAsplit.listIterator();
while (it.hasNext()) {
// Get from the list.
String current = it.next();
// Apply the transformation.
String newValue = current.replace("TAT", "Y");
// Set back into the list.
it.set(newValue);
}
And if you want to print the new values out:
System.out.println(DNAsplit);
Why dont you create a hashmap that has a key-value and use it during the load time to populate this list instead of revising it later ?
Map<String,String> dnaMap = new HashMap<String,String>() ;
dnaMap.push("X","XXX");
.
.
.
dnaMap.push("Z","ZZZ");
And use it like below :
//Use the hash map to lookup the temp key
temp= text.substring(i, Math.min(i + 3, text.length()));
DNAsplit.add(dnaMap.get(temp));

Merge two lists on index

I have two lists containing the same type of objects. Each object has an int, a string and some other stuff where the int is its index.
Here is the object that both lists are holding:
public class ListElement
{
private int index;
private String data;
private String some;
private String other;
private String stuff;
// gets, sets...
}
What i want is to take List A's index and "some other stuff" and replace its string "data" with the one from List B. The one it takes from List B should match the index of List A. I hope this is understandable.
EDIT: It should be noted that the index int inside the object has nothing to do with the actual position of the object in the list. Its for other porpuses
UPDATE: You mentioned that the index field of your ListElement has no relationship with its actual place in its containing List.
You just happen to have a field with a random name that you want to compare both list on (join on). This solution uses nested loops to compare every element in one list with every element in the other list.
for (int iA = 0; iA < listA.size(); iA++) //iterate over listA
{
ListElement currentElement = listA.get(iA);
for (int iB = 0; iB < listB.size(); iB++) //iterate over listB
{
ListElement other = listB.get(iB);
if (other.index == currentElement.index) //compare the elements
{
//do stuff
currentElement.setData(other.getData());
break; //if only want first match
}
}
}
Assuming your both list have the same number of elements, you could do something like:
ListElement sourceElement, destElement;
for (int i =0; i<list1.size(); i++) {
sourceElement = list1.get(0);
destElement = list2.get(0);
sourceElement.setData(destElement.getData());
...
}
The first idea is probably not the brightest but I'll come to that later.
For (ListElement e : ListA) {
For (ListElement le : ListB) {
if (e.getIndex() = le.getIndex()) {
e.setData(le.getData());
}
}
}
So this is my first shot for what you wrote, but it's probably not the easiest way. To make it simpler and faster you could implement the interface Comparable and use sort, i this case you access the List elements by the index in ListElement (assuming you assure the indices are complete from 1..n).
My favored solution would be to use some kind of maps to store the index as key, and the ListElement as value, then it's just MapA.get(i).setData(MapB.get(i).getData()) This is fool-prove, as long as for every item in MapA there is an according item in MapB with the same index.
If you want to match on the index field on the ListItem object, try this:
for (ListItem listItemA : listA) {
for (ListItem listItemB : listB) {
if (listItemB.getIndex() == listItemA.getIndex()) {
listItemA.setData(listItemB.getData());
}
}
}
If you're interested in matching based on index within the List objects, try
for (int i = 0; i < listA.size(); i++) {
listA.get(i).setData(listB.get(i).getData());
}

Sort string-array using java

I have a vector in which which holds items of type string. i am able to add items to the vector using
public void AddItem(String value)
{
data[length] = value;
length++;
}
however i would like the vector to be sorted in ascending order once items are added to in any particular order for instance if i added these items
v.AddItem("10");
v.AddItem("20");
v.AddItem("30");
v.AddItem("40");
v.AddItem("50");
v.AddItem("90");
v.AddItem("70");
v.AddItem("80");
i would expect "90" to be the last item in the list. i tried using this
for (int i = length- 1; i>1;i++)
{
if (data[length -1].compareTo(data[length]) > 0)
{
data[length-1] = temp;
data[length]=data[length -1];
temp = data[length];
}
}
and it doesnt seem to work can anybody point me in the right direction?
Arrays.sort(data);
instead of
for (int i = length- 1; i>1;i++)
{
if (data[length -1].compareTo(data[length]) > 0)
{
data[length-1] = temp;
data[length]=data[length -1];
temp = data[length];
}
}
but recommend use collections, if random access - ArraysList, for example,
if consistent access to elements use LinkedList
List<YourType> list = new LinkedList<YourType>();
list.add(SomeValue);
Collections.sort(list);
If values distinct, you can use TreeSet, this Collection sort values when adding new value:
Set<YourType> set = new TreeSet<YourType>();
set.add(SomeValue);
// Collections.sort(list) - not needed, set already sorted :)
You can use Arrays.sort() (notice that you need to add import statement):
import java.util.Arrays; // or just: import java.util.*;
public void AddItem(String value)
{
data[length] = value;
length++;
Arrays.sort(data);
}
As other people have pointed out in the comments, the data structure you use is array, not Vector.

Sort an 2D array by number of hits

I have two ArrayLists:
Array 01:
ArrayList<String> uniqueFiletypes --> which contains unique filetypes (e.g .zip etc..)
Array 02:
ArrayList<Integer> countFiletypes --> which counts how many of each filetype there is, for example 8 .zip's
And to skip right to the question:
I need to make some kind of "ranking", which means the highest count of filetypes gets the first place, etc...
Another problem: It must be an Object[][] (to support JTable), so it is possible to show the result easily.
Example of output: I have 8 .zips, 5 .java and 2 .docx
Object[][] = {{"1", ".zip", "8"},{"2", ".java", "5"}, {"3", ".docx", "2"}}
Where {PLACE, FILETYPE, COUNT}
I'm assuming the order of the items in both lists matches. I.e. the first item in the uniqueFiletypes list has the number of hits equal to the first number in the countFiletypes list.
I would do the following:
Loop through the lists, adding the entries to a Map.
Sort the list of countFiletypes in descending order.
Pull the file types from the map, adding them in the order they're now in in the ordered list.
Something like the following might do the trick:
public static void main(final String[] args) {
final ArrayList<String> uniqueFileTypes = new ArrayList<String>();
uniqueFileTypes.add(".java");
uniqueFileTypes.add(".zip");
uniqueFileTypes.add(".docx");
final ArrayList<Integer> countFileTypes = new ArrayList<Integer>();
countFileTypes.add(5);
countFileTypes.add(8);
countFileTypes.add(2);
final Map<Integer, String> countedFileTypes = new HashMap<Integer, String>();
for (int i = 0; i< uniqueFileTypes.size(); i++ ) {
countedFileTypes.put(countFileTypes.get(i), uniqueFileTypes.get(i) );
}
Collections.sort(countFileTypes);
Collections.reverse(countFileTypes);
final Object[][] data = new Object[countedFileTypes.size()][3];
for(int i = 0; i<countedFileTypes.size(); i++) {
final Integer count = countFileTypes.get(i);
data[i] = new Object[]{(i+1), countedFileTypes.get(count), count};
System.out.println("{" + (i+1) + "," + countedFileTypes.get(count) + "," + count + "}");
}
}
The main method and the system out aren't really needed, I just used them for testing my solution, which produced this output:
{1,.zip,8}
{2,.java,5}
{3,.docx,2}
Granted, this implies a link between the number of hits and the file type which may not be true. For example, if the docx and the java file format both have 9 hits, this solution wouldn't work.
Is it possible for you to merge the two ArrayLists to a single HashMap<String, Integer>?
This map can hold the entries consisting of the unique filetype (String) and its count (Integer). I suggest this because you have a direct link between a filetype and its count - this "link" can be expressed by a HashMap entry.
The conversion of the HashMap to an Object[][] can be done this way:
for (Map.Entry<?,?> entry : map.entrySet()) {
model.addRow(new Object[] { entry.getKey(), entry.getValue() });
}
With the HashMap sorting gets also easier as you do not need to handle two independent array lists.
First approach: As you will work with JTable, Use TableRowSorter as shown in the demo example of tutorial page
Second approach: Assuming you need it not only for JTable
Object[][] array = {{"1", ".zip", "8"},{"2", ".java", "5"}, {"3", ".docx", "2"}};
List<Object[]>data = Arrays.asList(array);
Comparator<Object[]>comparator = new Comparator<Object[]>() {
#Override
public int compare(Object[] o1, Object[] o2) {
return ((String)o1[2]).compareTo((String)o2[2]);
}
};
Collections.sort(data, Collections.reverseOrder(comparator));
array = (Object[][]) data.toArray();

Categories

Resources