前言:前一篇文章说道的BaseExpandableListAdapter类的许多函数都通过调用helper.getHashList()这个函数用到了HashList类的数据,下面来介绍HashList。
一、首先看HashList的职责:
(一)对两种数据的封装:
1.歌曲名字首字母的集合-->keys
2.每个首字母与相应歌曲集合的映射-->maps
(二)对这些数据的操作
1.基于groupId和childId返回相应的实例
2.对keys的排序
3.对keys和maps的添加和移除
二、HashList类的变量:
2.1、代码
/**
* 键值集合
* */
private List<K> keys = new ArrayList<K>();
/**
* 键值对映射
* 一个K对应一个group
*/
private HashMap<K, List<V>> map = new HashMap<K, List<V>>();
/**
* 键值分类
*/
private KeySort<K, V> keySort;
2.2、HashList类中的map这个变量的数据结构示意图:
String对应了K,Mp3Info对应了V;
2.3、Mp3Info就是歌曲的实体类,声明代码如下:
package guoke.model;
import java.io.Serializable;
import java.util.List;
/*
* 一个mp3的实体类
*/
public class Mp3Info implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String id;
private String mp3Name; //mp3名字
private long mp3Size; //mp3大小
private String lrcName;
private String lrcSize;
private String url; //音乐uri
private String title; //音乐标题
private long mdstore_id;//媒体库的id
private long Duration; //时长
private String artist; //艺术家
private String album; //专辑
private long albumId; //专辑ID
private Boolean ischecked;
private Boolean isPrePare=false;
public Boolean getIsPrePare() {
return isPrePare;
}
public void setIsPrePare(Boolean isPrePare) {
this.isPrePare = isPrePare;
}
public Boolean getIschecked() {
return ischecked;
}
public void setIschecked(Boolean ischecked) {
this.ischecked = ischecked;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public long getAlbumId() {
return albumId;
}
public void setAlbumId(long albumId) {
this.albumId = albumId;
}
/**
* @return the artist
*/
public String getArtist() {
return artist;
}
/**
* @param artist the artist to set
*/
public void setArtist(String artist) {
this.artist = artist;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the duration
*/
public long getDuration() {
return Duration;
}
/**
* @param duration the duration to set
*/
public void setDuration(long duration) {
Duration = duration;
}
/**
* @return the mdstore_id
*/
public long getMdstore_id() {
return mdstore_id;
}
/**
* @param mdstore_id the mdstore_id to set
*/
public void setMdstore_id(long mdstore_id) {
this.mdstore_id = mdstore_id;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
private List<Mp3Info> mp3InfosList = null;
/**
* @return the mp3InfosList
*/
public List<Mp3Info> getMp3InfosList() {
return mp3InfosList;
}
/**
* @param mp3InfosList the mp3InfosList to set
*/
public void setMp3InfosList(List<Mp3Info> mp3InfosList) {
this.mp3InfosList = mp3InfosList;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Mp3Info() {
super();
}
@Override
public String toString() {
return "Mp3Info [id=" + id + ", lrcName=" + lrcName + ", lrcSize="
+ lrcSize + ", mp3Name=" + mp3Name + ", mp3Size=" + mp3Size
+ ", mp3Size=" + url +"]";
}
public String getMp3Name() {
return mp3Name;
}
public Mp3Info(String id, String mp3Name, long mp3Size, String lrcName,
String lrcSize,String url) {
super();
this.id = id;
this.mp3Name = mp3Name;
this.mp3Size = mp3Size;
this.lrcName = lrcName;
this.lrcSize = lrcSize;
this.url=url;
}
public void setMp3Name(String mp3Name) {
this.mp3Name = mp3Name;
}
public long getMp3Size() {
return mp3Size;
}
public void setMp3Size(long mp3Size) {
this.mp3Size = mp3Size;
}
public String getLrcName() {
return lrcName;
}
public void setLrcName(String lrcName) {
this.lrcName = lrcName;
}
public String getLrcSize() {
return lrcSize;
}
public void setLrcSize(String lrcSize) {
this.lrcSize = lrcSize;
}
}
2.4、HashList类中的KeySort是一个接口,,声明的代码:
/***
* 分类接口,根据V value返回K key
*
* @param <K>
* @param <V>
*/
public interface KeySort<K, Mp3Info> {
public K getKey(Mp3Info mp3Info);
}
2.5、KeySort接口只带了一个函数 getKey(),该函数能获取Mp3Info实例的首字母,也就是获取歌曲的首字母
三、HashList类的函数:
3.1、代码
/**
* 构造函数
*/
public HashList(KeySort<K, V> keySort) {
// TODO Auto-generated constructor stub
this.keySort = keySort;
}
/**
* 根据value值返回key
* 返回首字母的大写字母
*/
public K getKey(V v) {
//在AssortPinyinList类里实现了KeySort接口的getkey()函数
//返回名字的首字母的大写字母
return keySort.getKey(v);
}
/**
* 返回大写的首字母,根据int类型的id
*/
public K getKeyIndex(int key) {
//key存储着每个group对应的id
//一个group对应着一个key
//key--group--id
return keys.get(key);
}
/**
* 获取首字母的集合
*/
public List<K> getKeys(){
return keys;
}
/**
* 根据索引返回键值对,返回的是一组child
*/
public List<V> getChildList(int key) {
//得到group的id,map存储着List<V>
//源头还是从kerArr那里获得键值,即人名的首字母大写
//在从map里去映射的list
return map.get(getKeyIndex(key));
}
/**
* 取得V的实例
* key就是 group_id
* value就是 child_id
* @return 一个V类型的实例
*/
public V getChild(int key, int value) {
//先得到group的id,再得到该group下的child的id
return getChildList(key).get(value);
}
/**获取keys的长度*/
public int size() {
return keys.size();
}
/** 取得k的下标*/
public int indexOfKey(K k)
{
return keys.indexOf(k);
}
/** 清除所有实例*/
public void clear() {
for (Iterator<K> it = map.keySet().iterator(); it.hasNext(); map.remove(it.next()));
}
/**
* 在这里实现了分类
* 把每一个名字分到对应的group里面
*/
public boolean add(Object object) {
V v = (V) object;
K key = getKey(v);
//System.out.println("在add()里,key:"+key);
//
if (!map.containsKey(key)) {
//该list存放人名
List<V> list = new ArrayList<V>();
//添加人名到list
list.add(v);
//添加该人名的首大写字母
keys.add(key);
//
map.put(key, list);
} else {
//
map.get(key).add(v);
}
return false;
}
/**
* 移除 List<V>里的实例
*/
public boolean remove(Object v) {
// TODO Auto-generated method stub
//取得k
K k=getKey((V)v);
//取得k的下标
int k_index=indexOfKey(k);
//根据k的下标取得对应的子list,移除该对象
boolean b=getChildList(k_index).remove(v);
//如果k的下标对应的子list为空,移除k
if(getChildList(k_index).isEmpty()==true){
keys.remove(k);
}
return b;
}
/** 键值对排序 */
public void sortKeyComparator(Comparator<K> comparator) {
//对keyArr的元素以comparator定义的方式来排序
//即对group对应的key进行排序
Collections.sort(keys, comparator);
if(keys.contains("#")){
keys.remove("#");
keys.add((K) "#");
}
}
这些函数的作用就是:
1.基于groupId和childId返回相应的实例
2.对keys的排序
3.对keys和maps的添加和移除
此时可知HashList封装了比较见到的一些函数操作,我们在Mp3SortHelper类里封装一些对HashList的数据更复杂的操作,主要是排序:
3.2、Mp3SortHelper代码:
package guoke.sort_helper;
import guoke.model.Mp3Info;
import guoke.sort_map_uitls.HashList;
import guoke.sort_map_uitls.KeyComparator;
import guoke.sort_map_uitls.KeySort;
import guoke.sort_map_uitls.Mp3ListComparator_CN;
import guoke.sort_map_uitls.Mp3ListComparator_EN;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pinyin4j.PinyinHelper;
/**
* 封装了对HashList的一下复杂的操作,主要是排序
* */
public class Mp3SortHelper {
private List<Mp3Info> mp3List;
private Mp3ListComparator_CN mp3ListSort_CN = new Mp3ListComparator_CN();
private Mp3ListComparator_EN mp3ListSort_EN= new Mp3ListComparator_EN();
private KeyComparator keySort = new KeyComparator();
//1.声明并实例化HashList<String,String>这个类
private HashList<String,Mp3Info> hashList=new HashList<String,Mp3Info>
( //2.同时实例化 接口
new KeySort<String,Mp3Info>()
{
//3.实例化了接口的函数
public String getKey(Mp3Info mp3Info)
{
return getFirstChar(mp3Info.getTitle());
}
}
);
/**
* 构造函数,调用了add_And_sortMp3()函数
* 将mp3Infos添加到hashList,同时实现了排序
* */
public Mp3SortHelper(List<Mp3Info> sList){
this.mp3List=sList;
add_And_sortMp3();
}
/**
* 添加并排序
* */
private void add_And_sortMp3(){
// 分类
//str 代表数组中元素类型,从数组中第一个元素开始遍历,strList代表被遍历的数组名
for (Mp3Info mp3Info : mp3List) {
//调用的add()函数里面实现了分类功能
//每一次添加一个str都会对该str归类
hashList.add(mp3Info);
System.out.println("title = "+mp3Info.getTitle()+" getFirst = "+getFirstChar(mp3Info.getTitle()));
}
hashList.sortKeyComparator(keySort);
for(int i=0,length=hashList.size();i<length;i++)
{
<span style="color:#ff0000;">//真正在执行排序的代码在这里
//给每一个group的item排序,先排序英文,在排序中文
Collections.sort(hashList.getChildList(i),mp3ListSort_EN);
Collections.sort(hashList.getChildList(i),mp3ListSort_CN);</span>
}
}
//获得字符串的首字母 首字符 转汉语拼音
public String getFirstChar(String value) {
// 首字符
char firstChar = value.charAt(0);
// 首字母分类
String first = null;
// 是否是非汉字
String[] print = PinyinHelper.toHanyuPinyinStringArray(firstChar);
if (print == null) {
// 将小写字母改成大写
if ((firstChar >= 97 && firstChar <= 122)) {
firstChar -= 32;
}
if (firstChar >= 65 && firstChar <= 90) {
first = String.valueOf((char) firstChar);
} else {
// 认为首字符为数字或者特殊字符
first = "#";
}
} else {
// 如果是中文 分类大写字母
first = String.valueOf((char)(print[0].charAt(0) -32));
}
if (first == null) {
first = "?";
}
return first;
}
/**
* 返回上面定义 hashList对象
* */
public HashList<String, Mp3Info> getHashList() {
return hashList;
}
/**
* 汇总HashList中已排好序mp3Info到mp3Infos
* @return mp3Infos 汇总好的列表
* */
public List<Mp3Info> getMp3InfosFromHashList(){
List<Mp3Info> mp3Infos=new ArrayList<Mp3Info>();
List<String> keys = hashList.getKeys();
for(int i = 0;i<keys.size();i++){//遍历每一个首字母对应的列表
List<Mp3Info> temps = hashList.getChildList(i);
for(int j=0;j<temps.size();j++){//遍历每个列表,组个添加,完全顺序
mp3Infos.add(hashList.getChild(i, j));
}
}
return mp3Infos;
}
}
其中Mp3ListComparator_CN,Mp3ListComparator_EN和KeyComparator三个类分别是针对中文歌曲名,英文歌曲名和keys排序的比较函数,后面有时间再详细介绍.
Mp3SortHelper类起到的作用:
一.对hashList实例的封装
1.实例化一个hashList对象,并实现KeySort接口的
回调函数getkeys(),在hashList内部调用;
二.一些辅助操作
2.实现getFirst()函数,获取字符串的首字母
3.实现getMp3InfosFromHashList函数,
从hashList实例中提取出mp3Infos实例
BaseExpandableListAdapter通过Mp3SortHelper类对HashList类进行操作
四、代码模块结构图: