目录

数据样例:

需求:

分析:

注意事项:


数据样例:

冒号左边为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进行排序,获取最大值即可。

  1. 使用缓冲字符流逐行读取字符串,首先利用split的分割功能将冒号分割,左侧为用户ID,右侧字符串为好友群;
  2. 将右侧好友群使用逗号继续分割,得到一个字符串数组,利用length得到长度,即好友数量;
  3. 之后可以利用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();

注意事项:

  1. 使用字节流读取的话,可以在全部读完之后使用\n\r(win)进行切割,之后使用冒号和逗号切割,再进行接下来的操作。或者读取换行符的ASCII表的值:10配合循环。  --->  记事本:\r\n表示换行;    notepad++:\n表示换行。
  2. 如果不关流,文件会被占用,不能被其它程序调用或执行写操作,但允许只读操作。
  3. 内部比较器Comparator,负数表示第一个参数比较小;正数表示第一个参数比较大。
  4. 如果存在多个并列第一,需要在最后做一个循环判断,从第一个依次往后进行相邻元素的对比。
  5. 根据不同的功能模块进行方法的封装
  6. 全局变量与局部变量是可以同名的,使用this来进行区分
  7. ArrayList使用Object[]类型的elementData,size记录元素个数,length表示数组长度,二者不相等。数组没有使用final修饰。aslist的数组创建于Arrays类的内部类ArrayList里面,数组使用final修饰,不可进行更改操作。因此在使用交集时需要将第一个list重新转为ArrayList集合类型,防止报错。