问题
I have a problem about implementing binary search in substring. In my City object, there is a cityName variable as defined String. I want to enter any substring like "Sha" and it shows the result of "Sha". Except for this, there is a weight variable to sort descend city names. For example, the bigger weight value is at the top and the sort process is based on descending.
How can I do that? How can I add this to the comparater
area?
Here is my City Object
public class City implements Serializable{
private Integer cityWeight;
private String cityName;
}
Here is my code snippet shown below.
// Not implement Binary Search
public static Integer[] searchByCharacters(List<City> list, String sub) {
List<Integer> result = new ArrayList<>();
Collections.sort(list);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getCityName().contains(sub))
result.add(i);
}
return result.stream().toArray(Integer[]::new);
}
I want to implement binary search above the code snippet but it doesn't work.
public static Integer[] searchBySubStringCharacter(List<City> list, String sub) {
List<Integer> result = new ArrayList<>();
Comparator<City> comparator = new Comparator<City>() {
public int compare(City node1, City node2) {
boolean node1Contains = node1.getCityName().contains(sub);
boolean node2Contains = node2.getCityName().contains(sub);
if (node1Contains && !node2Contains) {
return 1;
} else if (!node1Contains && node2Contains ) {
return -1;
} else {
return 0;
}
}
};
Collections.sort(list, comparator);
for (int i = 0; i < list.size(); i++) {
int index = Collections.binarySearch(list, new City(sub), comparator);
if (index >= 0)
result.add(i);
}
return result.stream().toArray(Integer[]::new);
}
This code shows all city list and the result of binary search. How can I extract all city list from the result?
回答1:
binarySearch
accepts the key to be searched for having type the class of the objects in the list,
public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
So pass City
object in binarySearch
,
for (int i = 0; i < list.size(); i++) {
int index = Collections.binarySearch(list, new City(sub), comparator);
if (index >= 0)
result.add(i);
}
Also if you are using java8+, you can use lambda for Comparator
,
Comparator<City> comparator = (node1, node2) -> {
boolean node1Contains = node1.getCityName().contains(sub);
boolean node2Contains = node2.getCityName().contains(sub);
if (node1Contains && !node2Contains) {
return 1;
} else if (!node1Contains && node2Contains ) {
return -1;
} else {
return 0;
}
};
Update: To sort based on the weight in case of a match you need to use Integer.compare(node2.getCityWeight(), node1.getCityWeight())
,
Also iyou can not binarySearch
with same comparator as you don't know the weight of the city you are searching. you can use Stream,
public static Integer[] searchBySubStringCharacter(List<City> list, String sub) {
List<Integer> result = new ArrayList<>();
Comparator<City> comparator = (node1, node2) -> {
boolean node1Contains = node1.getCityName().contains(sub);
boolean node2Contains = node2.getCityName().contains(sub);
if (node1Contains && !node2Contains) {
return 1;
} else if (!node1Contains && node2Contains ) {
return -1;
} else {
return Integer.compare(node2.getCityWeight(), node1.getCityWeight());
}
};
Collections.sort(list, comparator);
return IntStream.rangeClosed(0, list.size() - 1)
.filter(i -> list.get(i).getCityName().contains(sub))
.boxed()
.toArray(Integer[]::new);
}
回答2:
You can add create city object from string and search like this:
public static Integer[] searchBySubStringCharacter(List<City> list, String sub) {
List<Integer> result = new ArrayList<>();
Comparator<City> comparator = new Comparator<City>() {
public int compare(City node1, City node2) {
boolean node1Contains = node1.getCityName().contains(sub);
boolean node2Contains = node2.getCityName().contains(sub);
if (node1Contains && !node2Contains) {
return 1;
} else if (!node1Contains && node2Contains) {
return -1;
} else {
return 0;
}
}
};
Collections.sort(list, comparator);
for (int i = 0; i < list.size(); i++) {
int index = Collections.binarySearch(list, new City(sub), comparator);
if (index >= 0)
result.add(i);
}
return result.stream().toArray(Integer[]::new);
}
, or avoid creating city object every iteration and accept city as an argument
public static Integer[] searchBySubStringCharacter(List<City> list, City sub) {
List<Integer> result = new ArrayList<>();
Comparator<City> comparator = new Comparator<City>() {
public int compare(City node1, City node2) {
boolean node1Contains = node1.getCityName().contains(sub.getCityName());
boolean node2Contains = node2.getCityName().contains(sub.getCityName());
if (node1Contains && !node2Contains) {
return 1;
} else if (!node1Contains && node2Contains) {
return -1;
} else {
return 0;
}
}
};
Collections.sort(list, comparator);
for (int i = 0; i < list.size(); i++) {
int index = Collections.binarySearch(list, sub, comparator);
if (index >= 0)
result.add(i);
}
return result.stream().toArray(Integer[]::new);
}
来源:https://stackoverflow.com/questions/61521463/how-can-i-implement-binary-search-in-substring-in-function-and-two-values-in-com