contains in HashSet<int[]>() - android

In android I'm trying to save grids that the user already have pressed.
Code snipping I’m using is:
// private
private HashSet<int[]> PlayerSelectedHashField = new HashSet<int[]>();
private boolean collisionDetected = false;
In a function I’m using
collisionDetected = PlayerSelectedHashField.contains(TmpPos); // -> Fail - not working
{doing something}
PlayerSelectedHashField.add(TmpPos); // int[] TmpPos - TmpPos is x y
The .add function is working as expected, but .contains always return false.
Why does it not working - and what can I do instead?

public boolean contains(Object o) {
return map.containsKey(o);
}
containsKey:
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
getNode:
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
It will not work since equals of arrays will do a == compare, and it will return true only if they point to the same instance.
Your problem could be fixed without work with Arrays.equals (the way to compare two arrays elements and not reference) (could be problematic (at least, for me.) i prefer an easy way)
Since you save X and Y coordinates, just make a class Point
public class Point {
public final int X;
public final int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
#Override
public boolean equals(Object obj)
{
if (obj == this) {
return true;
}
if (obj instanceof Point) {
Point pObj = (Point) obj;
return pObj.X == X && pObj.Y == Y;
}
return false;
}
#Override
public int hashCode()
{
int result = X;
result = 31 * result + Y;
return result;
}
}
then use Point class to save X, Y points.
Instead of create your custom point class, you can use the Android Point.
Example
Set<Point> points = new HashSet<Point>();
points.add(new Point(1, 3));
points.add(new Point(1, 4));
System.out.println(points.contains(new Point(1, 3)));
System.out.println(points.contains(new Point(1, 4)));
System.out.println(points.contains(new Point(1, 5)));

From the HashSet javadocs:
public boolean contains(Object o)
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
So, generally, if you don't know what happens when you call equals on a particular object type, then contains also may not behave as you expect. It is never a bad idea to make a class for a particular object if that object type has conceptual meaning in your program. If you do that, you can override the equals method to make sure it is behaving exactly as you want.

Related

Xamarin - error message displayed in wrong position in RecyclerView

I have validate method inside my RecyclerView Adapter , this method made to validate row before add new row to my adapter , the issue I face when I edit in last row validation error appear in wrong position , I trace my adapter and I am sure it give right position
here is image for reference
my code I check if focused item is last item and validation is passed to add new row
private void CheckNewItemAddMethod(int position)
{
if (Validate(position) && position == ItemCount - 1)
{
transactionItemModelList.Add(new TransactionItemModel() { ItemID = -1 });
NotifyItemInserted(transactionItemModelList.Count - 1);
}
}
private bool Validate(int pos)
{
ItemCustomViewHolder Passedholder = FindViewHolderByPoistion(pos);
bool valid = true;
int x = 0;
if (! int.TryParse(Passedholder.itemCount.Text, out x) || x == 0){
valid = false;
}
int intItemPrice = 0;
if (string.IsNullOrEmpty(Passedholder.itemName.Text) || !int.TryParse(Passedholder.itemPrice.Text, out intItemPrice) || intItemPrice == 0)
{
valid = false;
Passedholder.itemName.SetError(mContext.GetString(Resource.String.empty_field), null);
}else
{
Passedholder.itemName.SetError((string)null, null);
}
if (string.IsNullOrEmpty(Passedholder.itemPrice.Text))
{
valid = false;
Passedholder.itemPrice.SetError(mContext.GetString(Resource.String.empty_field), null);
}
else
{
Passedholder.itemPrice.SetError((string)null, null);
}
return valid;
}
Note when I scroll it back to right view
any one can guide me why that happen

How to compare absolute coordinates

I have a list of absolute points of screen like bellow :
355.2599 : 408.4894
353.31705 : 409.43512
341.44516 : 418.35184
329.3344 : 427.5607
314.9433 : 435.21622
304.6277 : 440.36212
292.61746 : 444.36887
And i have some other points like below :
160.66528 : 513.35834
319.33472 : 230.71161
304.3659 : 479.40076
How can i know second points is in first points?
for example when points different was less than 10 dp it should be return found;
private boolean checkValidate(List<Point> first, List<Point> second)
{
int accuracy = Helper.dpToPixel(this, 10);
int pointSize = first.size();
int pointFlag = 0;
List<Boolean> poinsValidation = new ArrayList<>();
for(Point line : second)
{
if(pointSize != 0 && pointFlag < pointSize)
{
if(Math.abs(first.get(pointFlag).x - line.x ) <= accuracy && Math.abs(first.get(pointFlag).y - line.y ) <= accuracy)
{
poinsValidation.add(true);
pointFlag++;
}
}
}
if(poinsValidation.size() == first.size())
{
return true;
}
return false;
}
I would suggest nested looping through both arrays. Although nested looping is not preferred, at this stage I cannot think of another way to do it.
private boolean checkValidate(List<Point> first, List<Point> second)
{
int accuracy = Helper.dpToPixel(this, 10);
int pointSize = first.size();
int pointSize2 = second.size();
int pointFlag = 0;
List<Boolean> poinsValidation = new ArrayList<>();
for(Point line : second)
{
for(Point points: first){
if(pointSize != 0 && pointSize2 != 0 && pointFlag < pointSize)
{
if(Math.abs(points.x - line.x ) <= accuracy && Math.abs(points.y - line.y ) <= accuracy)
{
poinsValidation.add(true);
pointFlag++;
}
}
}
}
if(poinsValidation.size() == first.size())
{
return true;
}
return false;
}
Let me know if this helps.

Problems with Else If statements in Android

I'm working on this program that uses a few lines of code that worked that last time I used them but the only difference this time is that I need to use else if's instead of a basic if else statement. Still trying to learn how to really use this but any help would be appreciated. My error is stemming from the if statement and I have a feeling it is to do with the float result; line.
private float caravan = 35;
private float wigwag = 25;
private float tent = 15;
private float caravan(float value){
return value * caravan;
}
private float wigwag(float value){
return value * wigwag;
}
private float tent(float value){
return value * tent;
}
Button bookButton;
public void onClick(View view) {
EditText bookAmount = (EditText)findViewById(R.id.txtNights);
EditText bookFinal = (EditText)findViewById(R.id.txtBooked);
float bookResult = Float.parseFloat(bookAmount.getText().toString());
float result;
RadioButton cbSelected = (RadioButton)findViewById(R.id.radCaravan);
if(cbSelected.isChecked()){
result = caravan(bookResult);
} else if (result == wigwag(bookResult)){
} else if (result == tent(bookResult)){
}
bookFinal.setText(String.valueOf(result));
}
Your problem is that you put a semicolon at the end of your statements, and you don't use the == operator:
if(cbSelected.isChecked()){
result = caravan(bookResult);
} else if (result = wigwag(bookResult);{
} else if (result = tent(bookResult);{
}
Fix by removing the semicolons and using the equality operator:
if(cbSelected.isChecked()){
result = caravan(bookResult);
} else if (result == wigwag(bookResult){
} else if (result == tent(bookResult){
}
used == instead of = operator
if (result == wigwag(bookResult))

EditText selection on focus not working

Since I am very disappointed in a way that Android is doing decimal input I decided to write my own EditDecimal control that inherits from EditText. I want it to select all on click and to put cursor on first position on focus. I don't want cursor to show because it's usless on most Android phones (you mostly cannot put it in right place and it makes me very nervous)
Problem is when you tap on control - FocusChanged is called but it does not set position of (hidden) cursor on first position but on position where user tapped. I can not find the problem... is there some other event that happens after FocusChange that moves cursor?
public class EditDecimal : EditText
{
// Every constructor is calling Initialize ...
private void Initialize()
{
FocusChange += OnFocusChanged;
Click += OnClicked;
SetCursorVisible(false);
}
private void OnFocusChanged(object sender, FocusChangeEventArgs e)
{
if (IsFocused)
SetSelection(1);
}
private void OnClicked(object sender, EventArgs e)
{
SelectAll();
}
}
I finnaly solved it. I had to subscribe to OnTouch event and to change cursor position from there.
public class EditDecimal : EditText
{
// Every constructor is calling Initialize ...
private InputMethodManager _imm ;
public int DecimalSpaces { get; set; }
readonly DecimalFormatSymbols _dfs = new DecimalFormatSymbols();
private void Initialize(Context context, IAttributeSet attrs)
{
AfterTextChanged += OnAfterTextChanged;
SetSelectAllOnFocus(true);
SetCursorVisible(false);
Touch += OnTouch;
_imm = (InputMethodManager)context.GetSystemService(Context.InputMethodService);
var a = context.ObtainStyledAttributes(attrs, Resource.Styleable.EditDecimal);
try
{
DecimalSpaces = a.GetInteger(Resource.Styleable.EditDecimal_decimalSpaces, 2);
}
finally
{
a.Recycle();
}
}
private void OnTouch(object sender, TouchEventArgs e)
{
base.OnTouchEvent(e.Event);
if (e.Event.Action == MotionEventActions.Up)
{
SelectAll();
}
}
protected override void OnFocusChanged(bool gainFocus, FocusSearchDirection direction, Rect previouslyFocusedRect)
{
base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);
SelectAll();
}
private void OnAfterTextChanged(object sender, AfterTextChangedEventArgs e)
{
const char ch1 = '.';
const char ch2 = ',';
switch (_dfs.DecimalSeparator)
{
case ch2:
{
if (Text.Contains(ch1.ToString()))
{
var position = Text.IndexOf(ch1);
if (Text.Contains(ch2.ToString()))
e.Editable.Delete(position, position + 1);
else
e.Editable.Replace(position, position + 1, ch2.ToString());
}
// we have to prevent showing two commas in number
var firstCommaPosition = Text.IndexOf(ch2);
var lastCommaPosition = Text.LastIndexOf(ch2);
if (firstCommaPosition > 0 && lastCommaPosition > 0 && firstCommaPosition != lastCommaPosition)
e.Editable.Delete(lastCommaPosition, lastCommaPosition+1);
}
break;
case ch1:
{
if (Text.Contains(ch2.ToString()))
{
var position = Text.IndexOf(ch2);
e.Editable.Delete(position, position + 1);
}
// we have to prevent showing two points in number
var firstPointPosition = Text.IndexOf(ch1);
var lastPointPosition = Text.LastIndexOf(ch1);
if (firstPointPosition > 0 && lastPointPosition > 0 && firstPointPosition != lastPointPosition)
e.Editable.Delete(lastPointPosition, lastPointPosition + 1);
}
break;
}
//thnx to http://stackoverflow.com/users/2240673/tom
var length = e.Editable.Length();
if (length <= 0) return;
if (NrOfDecimal(e.Editable.ToString()) > DecimalSpaces)
e.Editable.Delete(length - 1, length);
}
private int NrOfDecimal(string nr)
{
if (nr == null) return 0;
var nrCharArray = nr.ToCharArray();
var len = nr.Length;
var pos = len;
for (var i = 0; i < len; i++)
{
if (nrCharArray[i] != '.') continue;
pos = i + 1;
break;
}
return len - pos;
}
}
What came as suprize to me was a fact that EditText selection behaves differently if SetCursorVisible is set to true than when it is set to false. I thought that it was just visibility property.
Grepcode is your friend. It shows that TextView's onFocusChanged method checks if there's an Editor object defined for the View (which is the case with EditText) and a look at the Editor code shows this at line 889 ff:
// If a tap was used to give focus to that view, move cursor at tap position.
// Has to be done before onTakeFocus, which can be overloaded.
final int lastTapPosition = getLastTapPosition();
if (lastTapPosition >= 0) {
Selection.setSelection((Spannable) mTextView.getText(), lastTapPosition);
}
So perhaps the best way would be to write your own implementation of Editor. Although if have no idea right now how you attach that to your TextView resp. EditText. class.
Or you just set the selection back to the first position if that is what you want.

setting null value

i'm making a chart which contain x and y value from sqlite.
my code is like this :
Double a, b;
notesCursor.moveToFirst();
do {
a = notesCursor.getDouble(notesCursor.getColumnIndex(DbAdapter.KEY_ROWID));
b = notesCursor.getDouble(notesCursor.getColumnIndex(DbAdapter.KEY_RESULT));
mCurrentSeries.add(a, b);
}while(notesCursor.moveToNext());
when i didn't insert any x y value to my sqlite, the errors message came out... i want to add some code which when even i didn't insert any x y value to my database, the chart will come out with 0, 0 value..
i've been making a code like this :
Double a, b;
if(a==null && b==null){
mCurrentSeries.add(0.0, 0.0);
}
else{
notesCursor.moveToFirst();
do {
a = notesCursor.getDouble(notesCursor.getColumnIndex(DbAdapter.KEY_ROWID));
b = notesCursor.getDouble(notesCursor.getColumnIndex(DbAdapter.KEY_RESULT));
mCurrentSeries.add(a, b);
}while(notesCursor.moveToNext());
}
but i can't make it work, anyone can help me to solve this problem? thank you
You code INITIALISES the values to non null (0.0) but it never guarantees that they won't be rest to null before they are given to the mCurrentSeries.add method. In you previous code, if a and b start as not null, then the else in the if else will be exected, then the do while. If in the do while the noteCursor.getDouble returns null for either a or b, then a and/or b will be null. If what you need is for a and b to not be null when arriving into your mCurrentSeries object via the add method, you should modify that add method to give a and b some default values when they're null.
Your new code does not guarantee that a and b will be not null when passed to the mCurrentSeries.add method:
import java.util.HashMap;
import java.util.Map;
public class C {
Double a, b;
Map mCurrentSeries = new HashMap();
NotesCursor notesCursor = new NotesCursor();
public void yourMethod() {
if (a == null && b == null) {
mCurrentSeries.put(0.0, 0.0);
} else {
// notesCursor.moveToFirst();
do {
a = notesCursor.getDouble();
b = notesCursor.getDouble();
mCurrentSeries.put(a, b);
} while (notesCursor.moveToNext());
}
}
private static class NotesCursor {
boolean b = false;
public Double getDouble() {
return null;
}
public boolean moveToNext() {
return !b;
}
}
public static void main(String... args) {
C c = new C();
c.yourMethod();
System.out.println("a="+c.a);
System.out.println("b="+c.b);
}
}

Categories

Resources