[英]Find duplicates in List by 2 level deep property
我不確定如何稱呼 2 層深的屬性。
但是假設我們有List<FruitColor>
,其中Fruit
和Color
是 2 個實體。 (這些都是示例實體)一個fruit
可以有不同的color
,但是color
也可以有不同的fruit
。
public class FruitColor {
private String fruitColorId;
private Fruit fruit;
private Color color;
private int ripe; //1 to 3 where 1 unripe 2 normal 3 ripe
// more props, getters, etc.
}
public class Fruit {
private String fruitId;
private String fruitName;
// getters, etc.
}
public class Color {
private String colorId;
private String colorName;
// getters, etc.
}
我在考慮以下步驟:
fruitName
過濾所有重復項name
,但color
不同。 選擇保留哪一個的規則是季節/時間轉換指示器systemTransition
,它由范圍從0
到100
的double
屬性systemTransition
描述。0.5
factorialRipeness
,它是ripe * systemTransition
或ripe * (100 - systemTransition)
取決於我們在這個季節有多遠,一半是閾值。Color
的建議FruitColors
,按FactorialRipeness
排序 問題是,這可能可以通過很多 for 循環來實現,但我只是想知道是否有更有效的方法。 我確實找到了有關如何按屬性過濾的來源,但此解決方案不允許我過濾屬性(= fruitName
)的屬性。 Java 8 按屬性區分
我制作了一個有效的代碼示例(同樣是不同的實體)。 有沒有可以提高效率的部分? 我的意思是更高效,如果代碼可以更短和/或更快。 稍后我肯定會將該方法重構為更小的部分。 抱歉造成混亂,如果不使用完全相同的實體,這個問題真的很難解釋。
//logic in the method
{
List<FruitColor> fruitColors = getAllFCs();
//Remove if FC is neither colors that were chosen
fruitColors.removeIf(fc -> fc.getColor().getColorId() != presentColor.getColor().getColorId()
&& fc.getColor().getColorId() != futureColor.getColor().getColorId());
List<FruitColor> suggestedFruits = new ArrayList<>();
//Systemtransition is the season/time from 0 to 100, where 100 the fruit should be completely ripe with the corresponding color.
//If the time is less than half, it should pick the present color, which is the less ripe color.
boolean getPresentColorFruit = systemTransition < 50;
// --->This whole for-if-if-else-elseif-if-else part I wanted to make more "efficient" <---
for (FruitColor fruitColor : fruitColors) {
//First check for duplicate FCs
List<FruitColor> sameNameFruits = fruitColors.stream()
.filter(fc -> fc.getFruit().getName().equals(itemColor.getFruit().getName()))
.collect(Collectors.toList());
//If there is only one of the fruit, check if it's added already. If not, than add with proper ripeness
//FactorialRipeness is the "true" ripeness.
if (sameNameFruits.size() == 1 && !suggestedFruits.stream().anyMatch(fc -> fc.getFruit().getName().equals(sameNameFruits.get(0).getFruit().getName()))) {
FruitColor onlyOne = sameNameFruits.get(0);
if (onlyOne.getColor().getColorId() == presentColor.getColor().getColorId()) {
onlyOne.setFactorialRipeness(onlyOne.getRipeness() * systemTransition);
} else {
onlyOne.setFactorialRipeness(onlyOne.getRipeness() * (100 - systemTransition));
}
suggestedFruits.add(onlyOne);
// If there are multiple FCs, than the ripeness has to go down. Which prioritizes duplicate FCs more. (this part isn't logical with these entities, sorry)
} else if(!suggestedFruits.stream().anyMatch(fc -> fc.getFruit().getName().equals(sameNameFruits.get(0).getFruit().getName()))){
if (getPresentColorFruit) {
FruitColor fcWithPresentColor = sameNameFruits.stream()
.filter(fc -> fc.getColor().getColorId() == presentColor.getColor().getColorId()).findFirst()
.get();
fcWithPresentColor.setFactorialRipeness((fcWithPresentColor.getRipeness() - 0.5) * systemTransition);
suggestedFruits.add(fcWithPresentColor);
} else {
FruitColor fcWithFutureColor = sameNameFruits.stream()
.filter(fc -> fc.getColor().getColorId() == futureColor.getColor().getColorId()).findFirst()
.get();
//This part is also not logical, but if the presentColor is not chosen. Than we need to multiply by the opposite amount of the systemTransition
fcWithFutureColor.setFactorialRipeness((fcWithFutureColor.getRipeness() - 0.5) * (100 - systemTransition));
suggestedFruits.add(fcWithFutureColor);
}
}
}
//Sort by "true" ripeness value, from lowest to highest
Collections.sort(suggestedFruits, new FruitColorRipenessComparator());
return suggestedFruits;
}
/**
* @source https://stackoverflow.com/questions/2839137/how-to-use-comparator-in-java-to-sort
*/
public class FruitColorRipenessComparator implements Comparator<FruitColor> {
@Override
public int compare(FruitColor a, FruitColor b){
return a.getFactorialRipeness() < b.getFactorialRipeness() ? -1 : a.getFactorialRipeness() == b.getFactorialRipeness() ? 0 : 1;
}
}
作為一個可能的選項,您可以通過將FruitColor
實例存儲到Map
中,按其fruit
的name
屬性對實例進行分組。 然后將值轉儲到列表中。
它可以通過 Stream API 使用 Collector toMap(keyMapper,valueMapper,mergeFunction)
來實現。
選擇保留哪一個的規則是水果的成熟程度,從 0 到 100,這是水果的一個屬性
要實現mergeFunction
,這意味着解析映射到相同鍵的值,我們可以使用 static 方法BinaryOpearator.maxBy()
,它需要一個Comparator
。
比較FruitColor
實例的基於rape
屬性的fruit
字段的比較器可以用以下方式表示:
Comparator.comparingInt(fruitColor -> fruitColor.getFruit().getRipe())
或者作為:
Comparator.comparing(
FruitColor::getFruit,
Comparator.comparingInt(Fruit::getRipe)
)
整體實現可能如下所示:
List<FruitColor> fruitColors = // initializing the list
List<FruitColor> fruitColorsDistinct = fruitColors.stream()
.collect(Collectors.toMap(
fruitColor -> fruitColor.getFruit().getFruitName(), // keyMapper
Function.identity(), // valueMapper
BinaryOperator.maxBy( // mergeFunction - resolving duplicates
Comparator.comparingInt(fruitColor -> fruitColor.getFruit().getRipe())
)
))
.values().stream()
.toList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.