background
The customer has such a requirement:
There are a bunch of room names with different names in a room list, but there are always several room names with the same name. Then display the top ten data with the same name in the current room list in an Adapter.
then it means that a data structure with a length of 10 needs to be constructed, which contains at least the room name and the number of the same room name.
Then you have to traverse the entire original room name data. To put it simply: it is a list, and the list contains various names.
What the customer wants is the room names with the top ten most frequent name occurrences.
Ideas
Algorithm implementation:
- It is necessary to create a kv pair or hash table to store the current name and its corresponding number;
This implementation is relatively simple. It just traverses the entire room name. If there is an increase, put it in; otherwise, ignore it.
// 遍历获取数据
for (RoomInfo roomInfo : roomList) {
String roomName = roomInfo.getSubject();
// 添加 前缀展示
String roomNameWithPremix = RoomNameListAdapter.ROOM_PREMIX + roomName;
if (roomNameCountMap.containsKey(roomNameWithPremix)) {
int count = roomNameCountMap.get(roomNameWithPremix);
count++;
roomNameCountMap.put(roomNameWithPremix, count);
} else {
roomNameCountMap.put(roomNameWithPremix, 1);
}
}
- By arranging and reading the top ten data, you can consider usingPriorityQueue priority queue;
This is also my first time to use this object, and there is still a lot I don’t understand.
For details, please refer to the official documentation
The key point is the type of comparator:
PriorityQueue<RoomNameCountPair> queue = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
queue = new PriorityQueue<>(Comparator.comparingInt(RoomNameCountPair::getCount));
}
Among::
Can be used forReference.
- final code
HashMap<String, Integer> roomNameCountMap = new HashMap<>();
List<String> subjectWithTopTen = new ArrayList<>();
private List<String> getTopRoomNameList(List<RoomInfo> roomList, int limit) {
// 重新刷
roomNameCountMap.clear();
subjectWithTopTen.clear();
if (roomList.isEmpty()) {
return subjectWithTopTen;
}
// 遍历获取数据
for (RoomInfo roomInfo : roomList) {
String roomName = roomInfo.getSubject();
// 添加 前缀展示
String roomNameWithPremix = RoomNameListAdapter.ROOM_PREMIX + roomName;
if (roomNameCountMap.containsKey(roomNameWithPremix)) {
int count = roomNameCountMap.get(roomNameWithPremix);
count++;
roomNameCountMap.put(roomNameWithPremix, count);
} else {
roomNameCountMap.put(roomNameWithPremix, 1);
}
}
// 优先队列 queue 来对房间名称出现次数进行排序
PriorityQueue<RoomNameCountPair> queue = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
queue = new PriorityQueue<>(Comparator.comparingInt(RoomNameCountPair::getCount));
}
for (Map.Entry<String, Integer> entry : roomNameCountMap.entrySet()) {
queue.offer(new RoomNameCountPair(entry.getKey(), entry.getValue()));
// 是否大于限制的10个,如果是就弹出最高优先级的
if (queue.size() > limit) {
queue.poll();
}
}
while (!queue.isEmpty()) {
subjectWithTopTen.add(0, queue.poll().getRoomName());
}
return subjectWithTopTen;
}
How to understand PriorityQueue
Suppose we have the following mock data:
roomNameCountMap = {
"room1": 5,
"room2": 3,
"room3": 2,
"room4": 7,
"room5": 1,
...
// 共有20个键值对
}
During the execution of the code, the content of the actual data in queue
will change as follows:
- Initial state:
queue
is empty. - When creates
PriorityQueue
object, a comparatorComparator.comparingInt(RoomNameCountPair::getCount)
is specified, which will be based onRoomNameCountPair
object'scount
attribute to sort. - First loop iteration:
- Encapsulate "room1" and the corresponding count value 5 into
RoomNameCountPair
objects and addqueue
. queue
medium content[(room1, 5)]
.
- Encapsulate "room1" and the corresponding count value 5 into
- Second loop iteration:
- Encapsulate "room2" and the corresponding count value 3 into
RoomNameCountPair
objects and addqueue
. queue
medium content[(room2, 3), (room1, 5)]
.
- Encapsulate "room2" and the corresponding count value 3 into
- Third loop iteration:
- Encapsulate "room3" and the corresponding count value 2 into the
RoomNameCountPair
object and addqueue
. queue
medium content[(room3, 2), (room1, 5), (room2, 3)]
.
- Encapsulate "room3" and the corresponding count value 2 into the
- Fourth loop iteration:
- Encapsulate "room4" and the corresponding count value 7 into
RoomNameCountPair
objects and addqueue
. queue
medium content[(room3, 2), (room2, 3), (room1, 5), (room4, 7)]
.
- Encapsulate "room4" and the corresponding count value 7 into
- Fifth loop iteration:
- Encapsulate "room5" and the corresponding count value 1 into the
RoomNameCountPair
object and addqueue
. queue
medium content[(room5, 1), (room3, 2), (room2, 3), (room1, 5), (room4, 7)]
.
- Encapsulate "room5" and the corresponding count value 1 into the
- The next loop iteration will continue to insert elements according to the size of the count value, and when the size of
queue
exceeds the limit, the element with the smallest count value will be popped out. Finally, the first elements with the largest count value are retained inqueue
.limit
Since we specified the comparator when creating the PriorityQueue
object, the elements in queue
will be sorted from small to large according to the count value.