I already filtered a group of object against a specific string entered in the EditText and now I need to sort that list with the position of the specified string, how can I do that?
I am already done this
Filter Function
public void setFilter(String query) {
visibleList = new ArrayList<>();
query = query.toLowerCase(Locale.getDefault());
for (AccountProfile accountProfile : accountProfileList) {
if (accountProfile.getName().toLowerCase(Locale.getDefault())
.contains(query))
visibleList.add(accountProfile);
}
Collections.sort(visibleList, new AccountNameComparator());
}
AccountNameComparator
public class AccountNameComparator implements Comparator<AccountProfile> {
#Override
public int compare(AccountProfile first, AccountProfile second) {
return first.getName().compareTo(second.getName());
}
}
the list is sorted but it is based on the getname() I need to sort the list with specific substring of the getname()
To sort that list with the position of the specified string, you could try something like this:
public class AccountNameComparator implements Comparator<AccountProfile> {
private final String query;
public AccountNameComparator(String query) {
this.query = query;
}
#Override
public int compare(AccountProfile first, AccountProfile second) {
Integer f = first.getName().indexOf(this.query);
Integer s = second.getName().indexOf(this.query);
return f.compareTo(s);
}
}
There is slight change in above answer: like below
public class AccountNameComparator implements Comparator<AccountProfile> {
private final String query;
public AccoluntNameSortComparator(String query) {
this.query = query;
}
#Override
public int compare(AccountProfile first, AccountProfile second) {
String firstName = first.getName().toLowerCase();
String secoundName = second.getName().toLowerCase();
query = query.toLowerCase();
Integer f = firstName.indexOf(query);
Integer s = secoundName.indexOf(query);
return f.compareTo(s);
}
}
Related
I want to order nodes' chosen string variables. this is an homework due to tomorrow.
public void sortSongName() {
DefaultSongs sortedList = new DefaultSongs();
int temp= Integer.MAX_VALUE;
Song curr=root;
Song hold = null;
while(root.nextSong != null) {
if(curr.getSongName().charAt(0)<hold.getSongName().charAt(0)) {
hold=curr;
curr=root.nextSong;
}else {
curr=root.nextSong;
}
sortedList.createSong(root.nextSong.getSongName(),root.nextSong.getBandName() , root.nextSong.getDuration());
deleteSong(root.nextSong.getSongName());
sortSongName();
}
}
Assuming your song class look something like this
public class Song {
private String name;
public String name() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
And the DefaultSongs class is just a repo with a list of Songs
public class DefaultSongs {
private final List<Song> songList;
public DefaultSongs() {
this.songList = new ArrayList<>();
}
public List<Song> songList() {
return songList;
}
}
Simplest way would be to use java stream
public void sortSongsByName(){
songList.stream().sorted(Comparator.comparing(Song::name));
}
The simplest way is to use Collections.sort();
For example:
List<String> songs = Arrays.asList("Bam","Cam", "Am","Dam");
Collections.sort(songs);
System.out.println(songs);
This will give you the list in alphabetical order.
I have some tuples already made like so:
public GreenhouseControls() {
light = new Tuple<>("light", "off");
fans = new Tuple<>("fans", "off");
water = new Tuple<>("water", "off");
power = new Tuple<>("power", "on");
window = new Tuple<>("window", "good");
thermostat = new Tuple<>("thermostat","day");
}
and I'm trying to use a setVariable() method in the same class that will take in 2 string (for example, "light" and "on") and would use the first string to search the first variable of the tuple and when a match is found it would replace the second variable with the second string.
I tried adding the tuples to an ArrayList but I can't get the search part to work.
Is there a way to achieve this maybe with either an ArrayList or a HashSet?
Tuple class:
public static class Tuple<A,B> {
public final A eventName;
public final B status;
public Tuple(A eventName, B status) {
this.eventName = eventName;
this.status = status;
}
public String toString() {
return "(" + eventName + ", " + status + ")";
}
}
You can use a Map to create relationships between keys and values. In your case, a HashMap would be appropriate and would make your code much more concise and easy to read. You can use put(key,value) to set the value of a key and use get(key) to retrieve the value associated with a key.
final Map<String, String> map = new HashMap<>();
map.put("light","off");
//Etc..
//Get value
String light = map.get("light");//"off"
//Update value
map.put("light","on");
light = map.get("light");//"on"
If you are not allowed to change the structure of your code, you can implement it with your Tuple class using foreach loops like so:
import java.util.Arrays;
import java.util.List;
public class GreenhouseControls {
private final List<Tuple<String,String>> members;
public GreenhouseControls() {
members = Arrays.asList(
new Tuple<>("light", "off"),
new Tuple<>("fans", "off"),
new Tuple<>("water", "off"),
new Tuple<>("power", "on"),
new Tuple<>("window", "good"),
new Tuple<>("thermostat","day")
);
}
public void setVariable(final String eventName, final String status) {
for(final Tuple<String, String> tuple: members) {
if(tuple.getEventName().equals(eventName)) {
tuple.setStatus(status);
return;
}
}
throw new IllegalArgumentException("No event found with eventName " + eventName);
}
public String getVariable(final String eventName) {
for(final Tuple<String, String> tuple: members) {
if(tuple.getEventName().equals(eventName)) {
return tuple.getStatus();
}
}
return null;
}
public static class Tuple<A, B> {
private A eventName;
private B status;
public Tuple(final A eventName, final B status) {
this.eventName = eventName;
this.status = status;
}
#Override
public String toString() {
return "(" + eventName + ", " + status + ")";
}
public B getStatus() {
return status;
}
public void setStatus(B status) {
this.status = status;
}
public A getEventName() {
return eventName;
}
}
}
I've implemented how you could do this for a single variable of an object. i.e. "Light".
Is there a reason why you need to have a redundant variable captured as a tuple?
public class GreenhouseControls {
private String light;
public String getLightStatus() {
return light;
}
public void setLightStatus(String input)
{
if(input == "on" || input == "off")
this.light = input;
}
public static void main(String[] args)
{
GreenhouseControls controls = new GreenhouseControls();
controls.setLightStatus("on");
System.out.println(controls.getLightStatus());
controls.setLightStatus("off");
System.out.println(controls.getLightStatus());
}
}
The easier way is to use HashMap for your requirement as suggested by hev1. But if you still want to make use of the Tuple class, then here is one way of doing it.
Add getter methods to your Tuple class
public class Tuple<A,B> {
public final A eventName;
public final B status;
public Tuple(A eventName, B status) {
this.eventName = eventName;
this.status = status;
}
public String toString() {
return "(" + eventName + ", " + status + ")";
}
public A getEventName() {
return eventName;
}
public B getStatus() {
return status;
}
}
Then collect all your tuples in a List and pass it to your setVariable method. Within this method just check if the given eventName is present in any of the tuples. If yes, then remove that Tuple from the list and create a new Tuple with the given status and add it back to the list. Something like this:
void setVariable(String eventName, String status, List<Tuple>tuples) {
boolean isRemoved = tuples.removeIf(tuple -> tuple.getEventName().equals(eventName));
if(isRemoved) {
Tuple tuple = new Tuple(eventName, status);
tuples.add(tuple);
}
}
Hope this helps.
I try to compare different types with hamcrest. But I don't understand, how I have to build my own Matcher for the following problem:
String[] exp = new String[]{"x", "y", "z"};
DAO[] cur = getFromExternalWebservice();
Assert.assertThat("wrong strings", exp, Matchers.arrayContainingInAnyOrder(cur));
cur is an array of the following class:
class DAO {
public String id;
public String name;
}
The test above should actually compare the Strings within exp and the name property of the DAO objects within the array cur. I cannot change something on DAO (like adding a toString() method).
I can transform the results from the webservice into a names array, which I send to the Matcher like this:
String names[] = new String[cur.length];
for (int i = 0; i < cur.length; i++) {
names[i] = cur[i].name;
}
Assert.assertThat("wrong strings", exp, Matchers.arrayContainingInAnyOrder(names));
But this is ugly, how I can build a Matcher which compares the Strings without any copy of data?
I have implemented a first idea:
public class IsIn extends BaseMatcher<String> {
class DAOIterator implements Iterable<String>, Iterator<String> {
private final DAO[] collection;
private int idx;
public DAOIterator(DAO[] elements) {
this.collection = elements;
idx = 0;
}
#Override
public boolean hasNext() {
return (this.collection.length > this.idx);
}
#Override
public String next() {
return this.collection[this.idx++].name;
}
#Override
public Iterator<String> iterator() {
return new DAOIterator(this.collection);
}
}
private final DAO[] collection;
public IsIn(DAO[] elements) {
this.collection = elements;
}
#Override
public boolean matches(Object o) {
for (DAO d : this.collection) {
if (o == null ? d.name == null : o.equals(d.name)) {
return true;
}
}
return false;
}
#Override
public void describeTo(Description buffer) {
buffer.appendText("one of ");
buffer.appendValueList("{", ", ", "}", new DAOIterator(this.collection));
}
}
Call this on JUnit testcase:
String[] exp = new String[]{"x", "y", "z"};
DAO[] cur = getFromExternalWebservice();
Assert.assertThat("wrong strings", Arrays.asList(exp), Matchers.everyItem(new IsIn(cur)));
How do you make these two array lists into one array list so that it still works in my arrayAdapter. I cant remember how to go about doing this.
public class MyArrayAdapter extends ArrayAdapter<String>{
Context context;
ArrayList<String>mtitle;
ArrayList<String>mdesc;
public MyArrayAdapter(Context c, ArrayList<String>title, ArrayList<String>desc) {
super(c, R.layout.single_row, R.id.viewtitle, title);
...
use java been type array list.
Like:-
public class JBContacts {
public String strID = "";
public String strTitle = "";
public String getStrID() {
return strID;
}
public void setStrID(String strID) {
this.strID = strID;
}
public String getStrTitle() {
return strTitle;
}
public void setStrTitle(String strTitle) {
this.strTitle = strTitle;
}
}
ArrayList<JBContacts> mArrayListContacts;
JBContacts mJbContacts;
mArrayListContacts = new ArrayList<JBContacts>();
mJbContacts = new JBContacts();
strId = mJsonObjectContacts.getString(Constants.TAG_ID);
strTitle = mJsonObjectContacts
.getString(Constants.TAG_TITLE);
mJbContacts.setStrTitle(strTitle);
Needing to create an unspecified number of objects, I tried to create a builder that do that. All was well until I realized that my builder creates all objects with their properties having the same values.
So when I call the builder:
ValidationHelper v = new ValidationHelper.HelperBuilder()
.addHelper("ICAO Identifier", icaoIdentifier, rulesICAO)
.addHelper("Long Name", longName, rulesLongName)
.build();
... I'll have 2 objects and their properties will have values of the last object the builder was asked to create.
To start with, is factory builder the prudent approach to this? Secondly, is my builder salvageable?
Builder:
public class ValidationHelper {
private static ArrayList<HelperBuilder> validatorHelpers = new ArrayList();
public static class HelperBuilder {
private String txtFieldName;
private String txtFieldValue;
private List<Integer> valCodes = new ArrayList<Integer>();
private ArrayList<HelperBuilder> innerValidatorHelpers = new ArrayList<HelperBuilder>();
public HelperBuilder() {}
public final HelperBuilder addHelper(String txtFieldName, String txtFieldValue, int[] validationCodes) {
this.txtFieldName = txtFieldName;
this.txtFieldValue = txtFieldValue;
for( int i = 0; i < validationCodes.length; i++ ){
getValCodes().add((Integer) validationCodes[i]);
}
innerValidatorHelpers.add(this);
return this;
}
public final ValidationHelper build() {
return new ValidationHelper(this);
}
public String getTxtFieldName() {
return txtFieldName;
}
public String getTxtFieldValue() {
return txtFieldValue;
}
public List<Integer> getValCodes() {
return valCodes;
}
}//end HelperBuilder
private ValidationHelper(HelperBuilder helperBuilder) {
validatorHelpers = helperBuilder.innerValidatorHelpers;
}
public void setHelpers(ArrayList validatorHelpers) {
validatorHelpers = validatorHelpers;
}
public ArrayList getHelpers() {
return validatorHelpers;
}
}
EDIT/FIXED:
So for what it's worth, here's the revised builder. It needed another constructor that could properly initialize an instance of what it's supposed to build.
public class ValidationHelper {
private static ArrayList<HelperBuilder> validatorHelpers = new ArrayList();
public static class HelperBuilder {
private String txtFieldName;
private String txtFieldValue;
private List<Integer> valCodes = new ArrayList<Integer>();
private ArrayList<HelperBuilder> innerValidatorHelpers = new ArrayList<HelperBuilder>();
public HelperBuilder() {}
public HelperBuilder(String txtFieldName, String txtFieldValue, int[] validationCodes) {
this.txtFieldName = txtFieldName;
this.txtFieldValue = txtFieldValue;
for (int i = 0; i < validationCodes.length; i++) {
valCodes.add((Integer) validationCodes[i]);
}
}
public final HelperBuilder addHelper(String txtFieldName, String txtFieldValue, int[] validationCodes) {
innerValidatorHelpers.add( new HelperBuilder(txtFieldName, txtFieldValue, validationCodes) );
return this;
}
public final ValidationHelper build() {
return new ValidationHelper(this);
}
public String getTxtFieldName() {
return txtFieldName;
}
public String getTxtFieldValue() {
return txtFieldValue;
}
public List getValCodes() {
return valCodes;
}
}//end HelperBuilder
private ValidationHelper(HelperBuilder helperBuilder) {
validatorHelpers = helperBuilder.innerValidatorHelpers;
}
public ArrayList getHelpers() {
return validatorHelpers;
}
}
Each time you just overwrite the values in
private String txtFieldName;
private String txtFieldValue;
and the last one winns. So you create only 1 HelperInstance here
ValidationHelper v = new ValidationHelper.HelperBuilder()
and the fields name and value are overwritten each time you call addHelper(). But you need to create an instance for each "configuration". So addHelper should create a new Instance and add it into
private ArrayList<HelperBuilder> innerValidatorHelpers = ...;
If you want to build objects with different values you have to either
alter the builder between creating the objects so it will build something different.
instruct the builder to change the values automatically e.g. use a counter, or filename based on the date, or provide a list of values.