我有一个简单的java方法,它根据从RGB转换的HSB值返回颜色。它工作(需要一些调整),但我使用一系列其他if和嵌套if语句来返回我想要的数据。我听说过HashMaps和String Factories更好,但我看不出它们如何使用远程数据。是否有更好的解决方案适用于这样的远程数据?
段:
public static String getColorName() {
getHSB(rgb);
if(hsbH >= 45 && hsbH < 75) {
if(hsbS > 0 && hsbS < 45 && hsbB > 70){
return "White/Off White";
} else if(hsbS > 0 && hsbS < 45 && hsbB < 10) {
return "Dark Yellow";
} else {
return "Yellow";
}
} else if(hsbH >= 15 && hsbH < 45) {
if(hsbS > 0 && hsbS < 45 && hsbB > 70){
return "White/Off White";
} else if(hsbS > 0 && hsbS < 45 && hsbB < 10) {
return "Dark Orange";
} else {
return "Orange";
}
...
答案 0 :(得分:5)
如果您有一个范围维度,则可以TreeMap
使用floorEntry()
或ceilingEntry()
。但对于多个范围的维度,我并没有真正看到如何实现这一目标。
相反,我要做的是指定某种规则对象:
public class Rule{
private int maxH = Integer.MAX_VALUE;
private int maxS = Integer.MAX_VALUE;
private int maxB = Integer.MAX_VALUE;
private int minH = Integer.MIN_VALUE;
private int minS = Integer.MIN_VALUE;
private int minB = Integer.MIN_VALUE;
public Rule maxH(int maxH){this.maxH=maxH;return this;}
public Rule minH(int minH){this.minH=minH;return this;}
public Rule maxS(int maxS){this.maxS=maxS;return this;}
public Rule minS(int minS){this.minS=minS;return this;}
public Rule maxB(int maxB){this.maxB=maxB;return this;}
public Rule minB(int minB){this.minB=minB;return this;}
public boolean appliesTo(HSB hsb){
return minH < hsb.getH() && hsb.getH() < maxH &&
minB < hsb.getB() && hsb.getB() < maxB &&
minS < hsb.getS() && hsb.getS() < maxS ;
}
}
像这样构建它们:
Rule rule = new Rule().maxB(123).minH(45).maxH(122);
并将它们与字符串一起保存在地图中(您可能希望首先实现equals()/ hashCode())。
现在迭代地图的entrySet(),当规则适用时,你有你的颜色名称。
答案 1 :(得分:1)
仔细观察,代码中有很多重复和非常明显的结构!这就是我提出的,据我所知,大部分工作是在我最喜欢的IDE中使用自动重构完成的:
public static String getColorName() {
getHSB(rgb);
if (hsbH < 15)
return colorName(hsbB, hsbS, "Red");
if (hsbH < 45)
return colorName(hsbB, hsbS, "Orange");
if (hsbH < 75)
return colorName(hsbB, hsbS, "Yellow");
//...
}
private static String colorName(int hsbB, int hsbS, String color) {
final boolean smallSaturation = hsbS > 0 && hsbS < 45;
if (smallSaturation) {
if (hsbB > 70)
return "White/Off White";
if (hsbB < 10)
return "Dark " + color;
}
return color;
}
如果您使用 Sean Patrick Floyd 使用TreeMap
的建议,这段代码会更简单(我可以帮助自己):
public static String getColorName(final int hsbH, final int hsbB, final int hsbS) {
NavigableMap<Integer, String> colorRanges = new TreeMap<Integer, String>();
colorRanges.put(0, "Red");
colorRanges.put(15, "Orange");
colorRanges.put(75, "Yellow");
//...
return colorName(hsbB, hsbS, colorRanges.floorEntry(hsbH).getValue());
}
请注意,colorRanges
范围应定义一次并重复使用。
冒险被贬低是一种很好的方式,你可以使用Scala和简单的DSL来写这个:
implicit def toIntBetween(x: Int) = new {
def between(left: Int) = new {
def and(right: Int) = {
x >= left && x < right
}
}
}
def getColorName = {
if(hsbH between 45 and 75) {
//...
}
}
花式if(hsbH between 45 and 75)
构造实际上转换为:
if(toIntBetween(hsbH).between(45).and(75))
答案 2 :(得分:1)
创建HSB类绝对可以使代码更具可读性。下面我使用的ceilingEntry()
TreeMap
方法可以被认为比具有明确最小值和最大值的众多if语句更不易读。但是,它具有不留任何漏洞的额外好处。 (即,如果某人设置范围为0-5,6-10等,if
语句需要包含<=
或=>
作为比较的一部分,或者是一个差距。)
public class HueSatBright {
int hue,sat, brightness;
static TreeMap<Integer,String> colorMap = new TreeMap<Integer,String>();
static {
colorMap.put(15,"Red");
colorMap.put(45,"Orange");
colorMap.put(75,"Yellow");
}
HueSatBright(int hue, int sat, int brightness) {
this.hue = hue;
this.sat = sat;
this.brightness = brightness;
}
public String toString() {
return (isKindaWhite()) ? "White/Off White" : getModifier() + getBaseColor();
}
public boolean isKindaWhite() {
return (sat > 0 && sat < 45 && brightness > 70);
}
public String getModifier() {
return (sat < 10) ? "Dark " : "";
}
public String getBaseColor() {
return colorMap.ceilingEntry(hue).getValue();
}
}