Kotlin logic conversion to Java problem with method "contains" - java

I'm trying to use the following piece of code posted on goo.gl/av3tJD
val supportsDistortionCorrection = characteristics.get(
CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES)?.contains(
CameraMetadata.DISTORTION_CORRECTION_MODE_HIGH_QUALITY) ?: false
I see the code is in Kotlin, which I know very little about.
I want to convert the code to Java.
I'm trying the following:
Boolean hasNoiseReduction = false;
//cc is my previously defined CameraCharacteristics object
if(cc.get(CameraCharacteristics.DISTORTION_CORRECTION_AVAILABLE_MODES).contains("some string"))hasNoiseReduction = true;
The method contains is throwing me off. I don't believe is the method contains used in the String class.
Any advice is needed

it.first at that point in the code is referring to the first element of the Pair created above, containing a CameraCharacteristics instance. The get on this returns an IntArray (int[] in Java terms), and the contains method from the Kotlin standard library checks whether the given constant is in that array.
val cameraCharacteristics: CameraCharacteristics = it.first
val capabilities: IntArray = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)!!
capabilities.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)
You could check this in Java by - for example - looping through the array elements and seeing if you find the value. A primitive implementation for this:
CameraCharacteristics cameraCharacteristics = ...;
final int[] capabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
boolean contains = false;
for (final int capability : capabilities) {
if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
contains = true;
break;
}
}
// use result

Related

Optional tags within XML document?

I'm working on a missile-combat oriented game written in java that reads missile types with settings from an XML document. Each missile has many different parameters that can clog up the XML sometimes and make it hard to handle each missile type. What I am wondering is if it would be possible to code the XML parsing section of the code so that I can put in only the options that will be different from a default value. For example, one of the parameters is "nuclear," which can be true or false to indicate a nuclear missile. Would it be possible to write the code so that if is not present, it defaults to "false?"
Here is a missile type in the XML:
<MissileType ID="1" Name="Tomahawk">
<AssetID>15</AssetID>
<Purchasable>true</Purchasable>
<SpeedIndex>1</SpeedIndex>
<MissileCost>550</MissileCost>
<BlastRadiusIndex>2</BlastRadiusIndex>
<RangeIndex>3</RangeIndex>
<MaxDamageIndex>3</MaxDamageIndex>
<Nuclear>false</Nuclear>
<Tracking>true</Tracking>
<ECM>true</ECM>
</MissileType>```
Here is the code that parses the missile type:
for(int i = 0; i < ndeMissileTypes.getLength(); i++)
{
try
{
Element ndeMissileType = (Element)ndeMissileTypes.item(i);
byte cID = GetByteAttribute(ndeMissileType, XMLDefs.ID);
String strName = GetStringAttribute(ndeMissileType, XMLDefs.NAME);
int lAssetID = GetIntElement(ndeMissileType, XMLDefs.ASSET_ID);
boolean bPurchasable = GetBooleanElement(ndeMissileType, XMLDefs.PURCHASABLE);
byte cSpeedIndex = GetByteElement(ndeMissileType, XMLDefs.SPEED_INDEX);
int cMissileCost = GetIntElement(ndeMissileType, XMLDefs.MISSILE_COST);
byte cBlastRadiusIndex = GetByteElement(ndeMissileType, XMLDefs.BLAST_RADIUS_INDEX);
byte cRangeIndex = GetByteElement(ndeMissileType, XMLDefs.RANGE_INDEX);
byte cMaxDamageIndex = GetByteElement(ndeMissileType, XMLDefs.MAX_DAMAGE_INDEX);
boolean bNuclear = GetBooleanElement(ndeMissileType, XMLDefs.NUCLEAR);
boolean bTracking = GetBooleanElement(ndeMissileType, XMLDefs.TRACKING);
boolean bECM = GetBooleanElement(ndeMissileType, XMLDefs.ECM);
config.AddMissileType(cID, new MissileType(cID, bPurchasable, strName, lAssetID, bNuclear, bTracking, bECM, cSpeedIndex, cMissileCost, cRangeIndex, cBlastRadiusIndex, cMaxDamageIndex));
}
catch(Exception ex)
{
listener.LoadError(String.format("Error loading missile type at index %d: %s.", i, ex.getMessage()));
}
}
I would like it so that I can leave out lines from <MissileType> and have it return a default value for that position. For example, have a missile type that looks like this:
<MissileType ID="1" Name="Tomahawk">
<AssetID>15</AssetID>
<Purchasable>true</Purchasable>
<SpeedIndex>1</SpeedIndex>
<MissileCost>550</MissileCost>
<BlastRadiusIndex>2</BlastRadiusIndex>
<RangeIndex>3</RangeIndex>
<MaxDamageIndex>3</MaxDamageIndex>
</MissileType>
Which would return false for the missing boolean values at the end, essentially allowing me to only input the tags that are relevant to this particular missile type.
Of course you can. I can't see what your problem is. Just write
boolean bPurchasable = getBooleanElement(ndeMissileType, XMLDefs.PURCHASABLE, false);
where the 3-argument method is defined as
public boolean getBooleanElement(Element parent, QName name, boolean default) {
return parent.hasChild(name) ? GetBooleanElement(parent, name) : default
}
(Treat this as pseudo-code, because I don't know what API you are actually using. Note Java method names conventionally use an initial lower-case letter.)

Android specific find object by matching properties in a collection on predicate

I have a collection of 10,000 objects that have two properties: a string and a string[]
class Product
{
String name;
String[] aliases;
}
Each object is roughly 64 bytes, so we're looking at under a megabyte in memory for the whole collection, which seems manageable for Android to search in memory.
I want an exact match to either the single string, or any string in the array, and to then return the name property of the object.
However, android has some restrictions on Lambdas and .stream() that exclude many of the popular search solutions without forcing users to have OS 7.0 or above, which rules out roughly one third of users. I'd like to avoid that.
Currently, the following code is working, but seems terrible considering some of options I've seen out there which take advantage of streams and lambdas.
public String isProductOrAlias(String lowertext) {
//products is instantiated in the parent class
//as a List<Product> loaded into memory from a local file
try {
for (Product p: products) {
if(lowertext.equals(p.name.toLowerCase()))
return p.name;
if(p.aliases != null) {
for (String s: p.aliases) {
if(lowertext.equals(s.toLowerCase()))
return p.name;
}
}
}
} catch (Exception ex) {
return "";
}
return "";
}
What's the best way to achieve the same goal, given the restrictions of the environment? Ideally, we'd like to keep minSDK to 23 (6.0) and above.
Canonical Kotlin, which would work on any version of Android regardless of Java Streams since it doesn't use them would be:
data class Product(val name: String, val aliases: Array<String>)
// written as an extension function, but doesn't have to be...
fun List<Product>.isProductOrAlias(text: String): String {
return this.firstOrNull { product ->
product.name.equals(text, ignoreCase = true) ||
product.aliases.any { alias ->
alias.equals(text, ignoreCase = true)
}
}?.name ?: ""
}
fun test() {
// assume somewhere this was created
val products = listOf<Product>(...)
println(products.isProductOrAlias("something")) // prints name of Product or ""
}
See Kotlin API reference for the standard library:
collection extension function firstOrNull()
array extension function any()
string extension function equals()
Kotlin Elvis operator ?:
Kotlin Safecalls ?.

Java MessagePack null check

I am trying to get familar with Messagepack for Java.
I get the data via Mqtt. If the variable is not null everything is fine but the variable can also be null and in this case I will get this Exception: Expected Int, but got Nil (c0)
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(m.getPayload());
int someInt = unpacker.unpackInt();
String someString = unpacker.unpackString();
So far I was not able to figure out how to get NULL back
I want to avoid to use TRY/CATCH so currently I am using this way
int someInt = unpacker.getNextFormat().equals("NIL") ? unpacker.unpackInt() : null;
Is there a better way ?
I looked the javadoc of MessageUnpacker and it doesn't seem provide a better way.
The example code is very close of your way :
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(...);
while(unpacker.hasNext()) {
MessageFormat f = unpacker.getNextFormat();
switch(f) {
case MessageFormat.POSFIXINT:
case MessageFormat.INT8:
case MessageFormat.UINT8: {
int v = unpacker.unpackInt();
break;
}
case MessageFormat.STRING: {
String v = unpacker.unpackString();
break;
}
// ...
}
}
So I think that you are in the good path.
But if you repeat this retrieval multiple times(and it is very likely), you could introduce utility methods that does the job for you.
For example for unpackInt() :
public Integer unpackIntOrNull (MessageUnpacker unpacker){
return unpacker.getNextFormat() == MessageFormat.INT8 ?
unpacker.unpackInt() : null;
}
And now, it is very straight to unpack elements :
Integer einInt = unpackIntOrNull(unpacker);
Integer einAndereInt = unpackIntOrNull(unpacker);
...
MessageUnpacker has a method named tryUnpackNil. If the next byte is a nil value, this method reads it and returns true, otherwise reads nothing and returns false.
This can be used to skip over nil values, and unpack non-nil values with e.g.:
final MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(data);
final Integer value = unpacker.tryUnpackNil() ? null : unpacker.unpackInt();

Multiple if statements having incorrect output [duplicate]

This question already has answers here:
Multiple if statements with single else statement
(2 answers)
Closed 6 years ago.
I want to fill the acts array with values of some enum. While iterating I want to input commands from console, but my if statements don't find any match and I always get the output "Incorrect".
My code:
Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
System.out.println("Enter act: ");
Scanner in1 = new Scanner(System.in);
String s = in1.next();
acts[i] = new Action();
if (s.equals("rotate_forw"))
acts[i].type = ActionType.RotF;
if (s.equals("rotate_back"))
acts[i].type = ActionType.RotB;
if (s.equals("shift_forw"))
acts[i].type = ActionType.ShiftF;
if (s.equals("shift_back"))
acts[i].type = ActionType.ShiftB;
else
System.out.println("Incorrect");
}
Your else clause applies only to the last if statement, so you get the "Incorrect" output whenever s.equals("shift_back") is false.
Your statements should be replaced with a single if-else-if...-else statement, so that "Incorrect" is only printed if all the conditions are false :
Action[] acts = new Action[n];
for(int i = 0; i < n; i++) {
if (s.equals("rotate_forw"))
acts[i].type = ActionType.RotF;
else if (s.equals("rotate_back"))
acts[i].type = ActionType.RotB;
else if (s.equals("shift_forw"))
acts[i].type = ActionType.ShiftF;
else if (s.equals("shift_back"))
acts[i].type = ActionType.ShiftB;
else
System.out.println("Incorrect");
}
You should also consider what you want to assign to acts[i].type when the input is incorrect. Perhaps you should throw an exception in this case.
While #Eran's answer is correct, I'd like to suggest a different approach that encapsulates the enum with the translation from the external coding. Consider this:
public class EnumDemo
{
public static enum ActionType
{
Incorrect(""),
RotF("rotate_forw"),
RotB("rotate_back"),
ShiftF("shift_forw"),
ShiftB("shift_back");
private String code;
private ActionType(String code)
{
this.code = code;
}
public static ActionType fromString(String code)
{
return Arrays.stream(ActionType.values())
.filter(v->v.code.equals(code))
.findFirst()
.orElse(ActionType.Incorrect);
}
}
public static void main(String[] args)
{
String[] testData = {
"rotate_forw",
"rotate_back",
"shift_forw",
"shift_back",
"junk",
null };
Arrays.stream(testData)
.forEach(t->System.out.printf("\"%s\" -> ActionType.%s\n", t, ActionType.fromString(t)));
}
}
This uses the fact that enum constants can have associated data. I've added an instance variable code to hold the external encoding of each enum value. Then I added a static fromString(String code) method to the enum that looks up the provided code in the list of values. For 4 possibilities a simple linear search, equivalent to your if-then-else cascade, works fine. If there were dozens or more I'd set up a Map<String,ActionType> to handle the conversion.
The search using streams bears some explanation.
First create a Stream of enum values
Filter it to contain only enum values whose code matches the desired code (there should be only one)
Pick off the first entry, which comes back in a Optional. If nothing was found (i.e. the code is invalid) the Optional will be empty.
Use the orElse method to return the value if it exists or ActionType.Incorrect if not.
At first glance this might look inefficient since one expects that the filter() predicate has to scan the entire stream even if the desired element occurs early. This is a really nifty feature of Streams -- all intermediate streams are "lazy", so the filter won't iterate over the entire list if it finds the desired entry early. See this question for details.
Output:
"rotate_forw" -> ActionType.RotF
"rotate_back" -> ActionType.RotB
"shift_forw" -> ActionType.ShiftF
"shift_back" -> ActionType.ShiftB
"junk" -> ActionType.Incorrect
"null" -> ActionType.Incorrect
The last testcase shows the code is null-safe.
The biggest advantage is that the mapping is in the same place as the enum itself, so you won't have to hunt for the code when you add or remove an enum value. Also you can't forget to define the mapping since it's required by the enum's constructor.

Processing: manipulate variables by string names

I am importing a .txt file to use to run parts of my program. A certain part needs to manipulate boolean variables. However, I am using loadStrings() to interpret the text into Strings, with the individual lines called lines[]. I have a variable's name as a String and must reference the variable itself. Unfortunately, I have been unable to figure out how to do this.
boolean choice1 = false;
// lines[counter+2] is "choice1"
if (lines[counter+2] = false) {
println("statement is false");
counter += 4;
}
Obviously, the above statement doesn't work, nor does:
if (boolean(lines[counter+2]) = false) {
as it errors.
Also,
if (boolean(lines[counter+2]) == false) {
is not a possible solution as any word other than "true" when used in boolean() is false, so the above gives a false positive (pardon the pun).
If there is a solution to the same problem in java coding, I would be happy to see that as well.
P.S. If you have a solution, is there a way to not just reference the variable by its name, but also to change it? For example:
boolean(lines[counter+2]) = false;
or
lines[counter+2] = false;
obviously, the above are incorrect, but that idea.
You can't do that.
You could use a HashMap of String values to Boolean values though:
HashMap<String, Boolean> variableMap = new HashMap<String, Boolean>();
variableMap.put("myVariable", true); //set the value
boolean check = variableMap.get("myVariable"); //get the value
println(check);
variableMap.put("myVariable", false); //change the value
boolean checkAgain = variableMap.get("myVariable"); //get the new value
println(checkAgain);
More info can be found in the Processing reference.

Categories

Resources