英文:
Sort a map based on value which is an arraylist java 8
问题
我有一个 Hashmap `map<String, List<Student>>`。
    Student {
      String name;
      List<Date> absentDates;
    }
键值对如下:
    ["Class1", <Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
    ["Class2", <Student3  absentDates = [02/12/2010]>]
    ["Class3", <Student4  absentDates = null>]
如何使用 Java 8 流对此映射进行排序,排序基于映射值即 List<Student>。get(0).getAbsentDates().get(0),即每个列表中第一个 Student 对象的可为空的 absentDates
期望输出为
    ["Class2", <Student3  absentDates = [02/12/2010]>]
    ["Class1", <Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
    ["Class3", <Student4  absentDates = null>]
英文:
I have a Hashmap map<String, List<Student>>.
Student {
  String name;
  List<Date> absentDates;
}
Key Values pairs as follows:
["Class1",<Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
["Class2",<Student3  absentDates = [02/12/2010]>]
["Class3",<Student4  absentDates = null>]
How can I sort this map using java 8 steams as follows, based on map value ie, List<Student>.get(0).getAbsentDates().get(0) ie, a nullable absentDates of first Student object in each list
Expected output is
["Class2",<Student3  absentDates = [02/12/2010]>]
["Class1",<Student1  absentDates = [02/11/2010, 02/09/2010]><Student2  absentDates = [02/10/2010]>]
["Class3",<Student4  absentDates = null>]
答案1
得分: 1
步骤我所遵循的。
1. 使用entrySet遍历Map<String, List<Student>>
2. 转换为MapValues类{Key,List<Stundent>}。MapValue是自定义的包装类,用于保存键和值。
3. 为MapValues实现比较器,基于stundents.get(0).getAbsentDates().get(0),同时处理比较器中的null。
4. 使用Collectors.toMap进行收集,以保留顺序使用LinkedHashMap。
简而言之,
```java
Map<String, List<Student>> newmap = map.entrySet()
                                                .stream()
                                                .map(e -> new MapValues(e.getKey(), e.getValue()))
                                                .sorted(new MapValuesComp())
                                                .collect(Collectors.toMap(
                                                 MapValues::getKey, MapValues::getStdns, 
                                                             (e1, e2) -> e1, 
                                                            LinkedHashMap::new));
public class CustomMapSorting {
	public static void main(String[] args) throws ParseException {
		Map<String, List<Student>> map = new HashMap<>();
		SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
		// Class1 Stundent1
		Date s1Date1 = format.parse("02/11/2010");
		Date s1Date2 = format.parse("02/09/2010");
		Date[] s1absentDates = { s1Date1, s1Date2 };
		Student s1 = new Student("Student1", Arrays.asList(s1absentDates));
		// Class1 Stundent2
		Date s2Date1 = format.parse("02/10/2010");
		Date[] s2absentDates = { s2Date1 };
		Student s2 = new Student("Student2", Arrays.asList(s2absentDates));
		// Class2 Stundent3
		Date s3Date1 = format.parse("02/12/2010");
		Date[] s3absentDates = { s3Date1 };
		Student s3 = new Student("Student3", Arrays.asList(s3absentDates));
		// Class3 Stundent4
		Student s4 = new Student("Stundent4", null);
		List<Student> class1SundLst = Arrays.asList(s1, s2);
		map.put("Class1", class1SundLst);
		map.put("Class2", Arrays.asList(s3));
		map.put("Class3", Arrays.asList(s4));
		Map<String, List<Student>> newmap = map.entrySet()
												.stream()
												.map(e -> new MapValues(e.getKey(), e.getValue()))
												.sorted(new MapValuesComp())
												.collect(Collectors.toMap(MapValues::getKey, MapValues::getStdns, (e1, e2) -> e1, LinkedHashMap::new));
		// 打印排序后的值
		newmap.entrySet().stream().forEach(e -> System.out.println(e.getKey() + " : " + e.getValue().get(0).absentDates));
	}
}
class MapValues {
	String key;
	List<Student> stdns;
	public MapValues(String key, List<Student> stdns) {
		super();
		this.key = key;
		this.stdns = stdns;
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public List<Student> getStdns() {
		return stdns;
	}
	public void setStdns(List<Student> stdns) {
		this.stdns = stdns;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return key;
	}
}
class MapValuesComp implements Comparator<MapValues> {
	public int compare(MapValues o1, MapValues o2) {
		if (o1.stdns.get(0).absentDates == null) {
			return (o2.stdns.get(0).absentDates == null) ? 0 : 1;
		}
		if (o2.stdns.get(0).absentDates == null) {
			return 1;
		}
		return o2.stdns.get(0).absentDates.get(0).compareTo(o1.stdns.get(0).absentDates.get(0));
	}
}
class Student {
	String name;
	List<Date> absentDates;
	public Student(String name, List<Date> absentDates) {
		super();
		this.name = name;
		this.absentDates = absentDates;
	}
	@Override
	public String toString() {
		if (absentDates == null)
			return null;
		SimpleDateFormat format = new SimpleDateFormat("dd/mm/YYYY");
		return format.format(absentDates.get(0));
	}
}
英文:
Steps I followed.
- Map<String, List<Student>> Stream through the entrySet
 - convert to class MapValues{Key,List<Stundent>}. MapValue is the Custom wrapper class created to hold key and value
 - Implement Comaparator for MapValues based on stundents.get(0).getAbsentDates().get(0) and also handle null in comaprator
 - Collect using Collectors.toMap to preserve the order use LinkedHashMap
 
In Short the
Map<String, List<Student>> newmap = map.entrySet()
.stream()
.map(e -> new MapValues(e.getKey(), e.getValue()))
.sorted(new MapValuesComp())
.collect(Collectors.toMap(
MapValues::getKey, MapValues::getStdns, 
(e1, e2) -> e1, 
LinkedHashMap::new));
public class CustomMapSorting {
public static void main(String[] args) throws ParseException {
Map<String, List<Student>> map = new HashMap<>();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
// Class1 Stundent1
Date s1Date1 = format.parse("02/11/2010");
Date s1Date2 = format.parse("02/09/2010");
Date[] s1absentDates = { s1Date1, s1Date2 };
Student s1 = new Student("Student1", Arrays.asList(s1absentDates));
// Class1 Stundent2
Date s2Date1 = format.parse("02/10/2010");
Date[] s2absentDates = { s2Date1 };
Student s2 = new Student("Student2", Arrays.asList(s2absentDates));
// Class2 Stundent3
Date s3Date1 = format.parse("02/12/2010");
Date[] s3absentDates = { s3Date1 };
Student s3 = new Student("Student3", Arrays.asList(s3absentDates));
// Class3 Stundent4
Student s4 = new Student("Stundent4", null);
List<Student> class1SundLst = Arrays.asList(s1, s2);
map.put("Class1", class1SundLst);
map.put("Class2", Arrays.asList(s3));
map.put("Class3", Arrays.asList(s4));
Map<String, List<Student>> newmap = map.entrySet()
.stream()
.map(e -> new MapValues(e.getKey(), e.getValue()))
.sorted(new MapValuesComp())
.collect(Collectors.toMap(MapValues::getKey, MapValues::getStdns, (e1, e2) -> e1, LinkedHashMap::new));
//Printing the sorted values
newmap.entrySet().stream().forEach(e -> System.out.println(e.getKey() + " : " + e.getValue().get(0).absentDates));
}
}
class MapValues {
String key;
List<Student> stdns;
public MapValues(String key, List<Student> stdns) {
super();
this.key = key;
this.stdns = stdns;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<Student> getStdns() {
return stdns;
}
public void setStdns(List<Student> stdns) {
this.stdns = stdns;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return key;
}
}
class MapValuesComp implements Comparator<MapValues> {
public int compare(MapValues o1, MapValues o2) {
if (o1.stdns.get(0).absentDates == null) {
return (o2.stdns.get(0).absentDates == null) ? 0 : 1;
}
if (o2.stdns.get(0).absentDates == null) {
return 1;
}
return o2.stdns.get(0).absentDates.get(0).compareTo(o1.stdns.get(0).absentDates.get(0));
}
}
class Student {
String name;
List<Date> absentDates;
public Student(String name, List<Date> absentDates) {
super();
this.name = name;
this.absentDates = absentDates;
}
@Override
public String toString() {
if (absentDates == null)
return null;
SimpleDateFormat format = new SimpleDateFormat("dd/mm/YYYY");
return format.format(absentDates.get(0));
}
}
答案2
得分: 1
我尝试了使用来自@Rono的答案中的lambda的内联解决方案。这只是他解决方案的改进版本。
Map<String, List<Student>> res = map.entrySet()
    .stream()
    .sorted((o1, o2) -> {
        if (o1.getValue().get(0).absentDates == null) {
            return (o2.getValue().get(0).absentDates == null) ? 0 : 1;
        }
        if (o2.getValue().get(0).absentDates == null) {
            return 1;
        }
        return o2.getValue().get(0).absentDates.get(0).compareTo(o1.getValue().get(0).absentDates.get(0));
    })
    .collect(Collectors.toMap(Map.Entry::getKey, 
        Map.Entry::getValue, (e1, e2) -> e1, 
        LinkedHashMap::new));
英文:
I tried a inline solution using lambdas from the answer posted using @Rono. Just a improved version of his solution.
Map<String, List<Student>> res = map.entrySet()
.stream()
.sorted((o1, o2) -> {
if (o1.getValue().get(0).absentDates == null) {
return (o2.getValue().get(0).absentDates == null) ? 0 : 1;
}
if (o2.getValue().get(0).absentDates == null) {
return 1;
}
return o2.getValue().get(0).absentDates.get(0).compareTo(o1.getValue().get(0).absentDates.get(0));
}).
collect(Collectors.toMap(Map.Entry::getKey, 
Map.Entry::getValue,(e1, e2) -> e1, 
LinkedHashMap::new));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论