目录
数据样例:
需求:
分析:
注意事项:
数据样例:
冒号左边为ID,右边为用户的好友列表
A:B,C,D,F,E,O
B:A,C,E,K
C:F,A,D,I
D:A,E,F,L
E:B,C,D,M,L
F:A,B,C,D,E,O,M
G:A,C,D,E,F
H:A,C,D,E,O
......
需求:
求出有共同好友的用户对及他们的共同好友,如:
1 获取所有用户对应的好友数量 取人缘最好的用户
2 获取所有人的好友信息
3 获取制定两个用户的共同好友
4 将以上三部的结果集写在本地磁盘
分析:
1. 获取所有用户对应的好友数量 取人缘最好的用户
分析:使用Map存储信息,用户ID为key,好友数量为value。在对value进行排序,获取最大值即可。
- 使用缓冲字符流逐行读取字符串,首先利用split的分割功能将冒号分割,左侧为用户ID,右侧字符串为好友群;
- 将右侧好友群使用逗号继续分割,得到一个字符串数组,利用length得到长度,即好友数量;
- 之后可以利用Collections.sort或者List.sort的比较器对value进行排序,取出最大值。ye可以使用lambda表达式,利用stream().limit(3)取出TOP3用户ID
public class Demo01 {
public static void main(String[] args) {
//使用map来存储每个人对应的好友个数
Map<String,Integer> map = new HashMap<>();
try {
// 使用缓冲字符流读取文件中的数据
BufferedReader br = new BufferedReader(new FileReader("F:\\friendsnetwork.txt"));
String s;
while((s=br.readLine())!=null) {
String[] str1 = s.split(":");
//将每个key对应的好友个数存入map中
String key = str1[0];
String[] str2 = str1[1].split(",");
map.put(key, str2.length);
}
//对map的value进行遍历:提取map的entry
Set<Entry<String, Integer>> entrySet = map.entrySet();
for (Entry<String, Integer> entry : entrySet) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + ":" + value);
}
System.out.println("===============================");
/**
* 对map的value排序:将entry存入List集合中,利用比较器进行排序,
* 利用ArrayList的构造方法将Collection,set,List对象转为ArrayList类型
*/
ArrayList<Entry<String, Integer>> list = new ArrayList<>(entrySet);
Collections.sort(list, (o1,o2)->o2.getValue()-o1.getValue());
list.stream().limit(3).forEach(System.out::println);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.获取所有人的好友信息
分析:在1的基础上,将每个用户的好友信息拆分后得到String[],之后利用Arrays.aslist()将字符串数组转为只读类型的List集合。之后将用户ID作为key,将List集合作为value传入一个Map集合中,遍历输出,得到所有人的好友信息。
3.获取制定两个用户的共同好友
分析:在2的基础上,随机利用map.get(key)得到两个List的value提取出来,利用Collection提供的成员方法retainAll方法取交集,得到两人的共同好友。此时的value是只读形式的List,需要使用ArrayList的构造方法将其转为允许写操作的ArrayList类型的集合。
public class Demo02 {
public static void main(String[] args) throws Exception {
Map<String,List<String>> map = new HashMap<>();
BufferedReader br = new BufferedReader(new FileReader("F:/friendsnetwork.txt"));
String str;
while((str=br.readLine())!=null) {
String[] s1 = str.split(":");
String key = s1[0];
String[] arr = s1[1].split(",");
//怎么将字符串数组转为List集合
List<String> value= Arrays.asList(arr);
map.put(key, value);
}
//获取指定的两个共同好友,利用retainAll方法取交集
List<String> list1 = map.get("A");
ArrayList<String> arrayList = new ArrayList<>(list1);
arrayList.retainAll(map.get("F"));
System.out.println(arrayList);
}
}
4.将以上三部的结果集写在本地磁盘
分析:在3的基础上,利用类似选择排序的方式,对用户ID进行两两取交集。并将结果写入本地磁盘中。
//循环遍历所有两两用户ID的共同好友
Set<Entry<String, List<String>>> entrySet = map.entrySet();
ArrayList<Entry<String, List<String>>> arrayList = new ArrayList<>(entrySet);
//创建一个字符输出流对象,将内容写入"F:/副本.txt"中
BufferedWriter bw = new BufferedWriter(new FileWriter("F:/副本.txt"));
for(int i=0;i<map.size()-1;i++) {
for(int j=1;j<map.size();j++) {
List<String> v1 = arrayList.get(i).getValue();
ArrayList<String> value = new ArrayList<>(v1);
value.retainAll(arrayList.get(j).getValue()); //aslist生成的List不能读写,会报java.lang.UnsupportedOperationException
String s = arrayList.get(i).getKey() + "," + arrayList.get(j).getKey() + "=" + value;
System.out.println(s);
bw.write(s);
bw.newLine();
}
}
bw.flush();
bw.close();
注意事项:
- 使用字节流读取的话,可以在全部读完之后使用\n\r(win)进行切割,之后使用冒号和逗号切割,再进行接下来的操作。或者读取换行符的ASCII表的值:10配合循环。 ---> 记事本:\r\n表示换行; notepad++:\n表示换行。
- 如果不关流,文件会被占用,不能被其它程序调用或执行写操作,但允许只读操作。
- 内部比较器Comparator,负数表示第一个参数比较小;正数表示第一个参数比较大。
- 如果存在多个并列第一,需要在最后做一个循环判断,从第一个依次往后进行相邻元素的对比。
- 根据不同的功能模块进行方法的封装
- 全局变量与局部变量是可以同名的,使用this来进行区分
- ArrayList使用Object[]类型的elementData,size记录元素个数,length表示数组长度,二者不相等。数组没有使用final修饰。aslist的数组创建于Arrays类的内部类ArrayList里面,数组使用final修饰,不可进行更改操作。因此在使用交集时需要将第一个list重新转为ArrayList集合类型,防止报错。