What's the point of using the bitwise XOR operator "^" to get/generate the hashcode of an object? - flutter

While reading some code, it came to my attention that some developers use the bitwise XOR operator, ^, to generate the hashcode of an object.
What's the point of doing it like this? Does it have some advantages over other methods to get/generate the hashcode of an object?
Here is a code example.
class Student {
final String name;
final int age;
Student(this.name, this.age);
#override
bool operator ==(other) {
return (other is Student) && other.name == name && other.age == age;
}
#override
int get hashCode => age.hashCode ^ name.hashCode; // <-- Here
}

It has to be a single number, and the more it varies on more of the bits of any member of the object, the better.

Related

Use enum constructor directly in Dart

Is it possible to use the enum constructor directly?
void main() {
print(Test(1));
}
enum Test {
test1(1),
test2(2);
final int id;
const Test(this.id);
}
This will give the following error:
generative enum constructors can only be used as targets of redirection
I know that it can be solved like this:
enum Test {
test1(1),
test2(2);
final int id;
const Test(this.id);
factory Test.fromId(int id) {
return values.firstWhere((e) => e.id == id);
}
}
But it feels like there must be a way to avoid this boiler plate factory?
I don't think there is an easier way than that factory. My personal opinion is also that it really isn't that much of boiler plate, but that's subjective.
One reason I can think of why there isn't an easier method, is because the id in your case is not unique, this is perfectly valid:
enum Test {
test1(1),
secondtest1(1),
test2(2);
final int id;
const Test(this.id);
factory Test.fromId(int id) {
return values.firstWhere((e) => e.id == id);
}
}
Now you will never be able to get the secondtest1 using the fromId

How to automatic declare operator for class?

For example, I want operator+ to plus every field in class
class Test {
final int var1;
final int var2;
final int var3;
final int var4;
Test(this.var1, this.var2, this.var3, this.var4);
Test operator +(Test other) {
return Test(
var1 + other.var1,
var2 + other.var2,
var3 + other.var3,
var4 + other.var4,
);
}
}
This very cumbersum and duplicated, especially when I have many fields (let say 100), I just want to add every field.
Is there other way to do this faster? Why it didn't have default operator+?
This isn't possible, as dart isn't a reflective language, so its code can't inspect itself.
To give you a clearer idea, here an example of what you could use, but in Java, you could probably achieve what you're trying to do with this language feature.
So, long story short, you can't do this in dart, at the moment.
I found a solution to work around this.
By convert it to a map using json_serializable and iterate through the map
#JsonSerializable()
class Test {
final int var1;
final int var2;
final int var3;
final int var4;
Test(this.var1, this.var2, this.var3, this.var4);
factory Test.fromJson(Map<String, dynamic> json) => _$TestFromJson(json);
Map<String, dynamic> toJson() => _$TestToJson(this);
Test operator +(Test other) {
final thisJson = toJson();
final otherJson = other.toJson();
final Map<String, dynamic> result = {};
for (var key in thisJson.key) {
result[key] = thisJson[key] + otherJson[key];
}
return Test.fromJson(result);
}
}
*Note: this code is inefficient in term of performance (it has to encode and decode JSON), so don't do this if you call this operator a lot.

Can we set the precision of decimal points globally an dynamically in Flutter

I have a multi client accounting app. The preference of decimal points in a double is different for different clients. Is there any way to set the precision of double both in calculation and display globally ?
I'm afraid there's no way to do it.
I have an app which is very similar to yours, and I have created a class for all numbers:
const int precision = 3;
class NumberEntry implements Comparable<NumberEntry> {
final num value;
NumberEntry(num input) : value = _round(input);
static num _round(num input) {
return num.parse(input.toStringAsFixed(precision));
}
NumberEntry operator +(NumberEntry other) => NumberEntry(value + other.value);
NumberEntry operator -(NumberEntry other) => NumberEntry(value - other.value);
NumberEntry operator *(NumberEntry other) => NumberEntry(value * other.value);
NumberEntry operator /(NumberEntry other) => NumberEntry(value / other.value);
bool operator >(NumberEntry other) => value > other.value;
bool operator <(NumberEntry other) => value < other.value;
bool operator >=(NumberEntry other) => value >= other.value;
bool operator <=(NumberEntry other) => value <= other.value;
#override
int compareTo(NumberEntry other) {
if (value == other.value) {
return 0;
}
return value > other.value ? 1 : -1;
}
#override
String toString() {
return displayText;
}
String get displayText {
return value.toStringAsFixed(precision);
}
String get displayTextWithSign {
final String additionalSign = !value.isNegative ? '+' : '';
return additionalSign + displayText;
}
NumberEntry abs() {
return NumberEntry(value.abs());
}
}
You might modify it to suit your needs.

Can I store in a variable, the path to an element in a Map in Dart / Flutter?

I want to store in a variable, the path to an element in a Map for quicker access later on
class Student{
String name;
int age;
Icon icon;
Color color;
Student(this.name, this.age, this.icon, this.color);
}
Student student_1 = Student('James', 14, Icon(Icons.label),Colors.green);
Student student_2 = Student('Andy', 12, Icon(Icons.label),Colors.blue);
Student student_3 = Student('Peter', 13, Icon(Icons.label),Colors.green);
Student student_4 = Student('Cathy', 15, Icon(Icons.label),Colors.pink);
Student student_5 = Student('Pamela', 14, Icon(Icons.label),Colors.amber);
Map<Student,dynamic> mapStudent = {student_1 : [student_2 , {student_3 : [student_4 , student_5,
student_2]}]};
var tmp = mapStudent[student_1][1][student_3][0];
The path I want to store is[student_1][1][student_3] so I can later access the details in that element without having to go through a loop. Is it possible?
I came across a Class called PathMap class but don't know how to use it or whether it is meant for what I'm trying to achieve.
PathMap class
I had a simmilar use case recently in which I had a List of items which belonged to a hierarchy for example:
factory Comment(
{required int id,
required String content,
required DateTime inserted,
CommentAuthor? commentAuthor,
int? parentId})/// This is the most important attribute `parentId`
Comments could be nested via its parentId just like Student in your map implementation.
I saw that hierarchy could be more correctly represented using trees so I created a slimmed down tree data structure like this one:
/// Simple N-ary tree data structure
class Node<T> {
final T value;
final List<Node<T>> children;
Node(this.value, {List<Node<T>>? children}) : children = children ?? [];
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is Node &&
runtimeType == other.runtimeType &&
value == other.value &&
DeepCollectionEquality().equals(other.children, children);
#override
int get hashCode => value.hashCode ^ children.hashCode;
bool get isLeaf => children.isEmpty;
}
With this tree implementation now you have a safe, strongly typed hierarchy.
Extra : Transform list into tree (adapted from here)
/// Sample usage :
/// ```
/// List<Node<Comment>> commentListToTree(List<Comment> comments) {
/// return listToTree<Comment, int>(
/// comments,
/// idSelector: (c) => c.id,
/// parentIdSelector: (c) => c.parentId,
/// rootId: null,
/// );
/// }
/// ```
///
List<Node<T>> listToTree<T, IdType>(
List<T> list, {
required IdType? Function(T) idSelector,
required IdType? Function(T) parentIdSelector,
required IdType? rootId,
}) {
if (list.isEmpty) return [];
final tree = <Node<T>>[];
for (final item in list.where((e) => parentIdSelector(e) == rootId)) {
tree.add(Node<T>(
item,
children: listToTree(
list,
idSelector: idSelector,
parentIdSelector: parentIdSelector,
rootId: idSelector(item),
)));
}
return tree;
}

Case-insensitive indexing with Hibernate-Search?

Is there a simple way to make Hibernate Search to index all its values in lower case ? Instead of the default mixed-case.
I'm using the annotation #Field. But I can't seem to be able to configure some application-level set
Fool that I am ! The StandardAnalyzer class is already indexing in lowercase. It's just a matter of setting the search terms in lowercase too. I was assuming the query would do that.
However, if a different analyzer were to be used, application-wide, then it can be set using the property hibernate.search.analyzer.
Lowercasing, term splitting, removing common terms and many more advanced language processing functions are applied by the Analyzer.
Usually you should process user input meant to match indexed strings with the same Analyzer used at indexing; configuring hibernate.search.analyzer sets the default (global) Analyzer, but you can customize it per index, per entity type, per field and even on different entity instances.
It is for example useful to have language specific analysis, so to process Chinese descriptions with Chinese specific routines, Italian descriptions with Italian tokenizers.
The default analyzer is ok for most use cases, and does lowercasing and splits terms on whitespace.
Consider as well that when using the Lucene Queryparser the API requests you the appropriate Analyzer.
When using the Hibernate Search QueryBuilder it attempts to apply the correct Analyzer on each field; see also http://docs.jboss.org/hibernate/search/4.1/reference/en-US/html_single/#search-query-querydsl .
There are multiple way to make sort insensitive in string type field only.
1.First Way is add #Fields annotation in field/property on entity.
Like
#Fields({#Field(index=Index.YES,analyze=Analyze.YES,store=Store.YES),
#Field(index=Index.YES,name = "nameSort",analyzer = #Analyzer(impl=KeywordAnalyzer.class), store = Store.YES)})
private String name;
suppose you have name property with custom analyzer and sort on that. so it's not possible then you can add new Field in index with nameSort apply sort on that field.
you must apply Keyword Analyzer class because that is not tokeniz field and by default apply lowercase factory class in field.
2.Second way is that you can implement your comparison class on sorting like
#Override
public FieldComparator newComparator(String field, int numHits, int sortPos, boolean reversed) throws IOException {
return new StringValComparator(numHits, field);
}
Make one class with extend FieldComparatorSource class and implement above method.
Created new Class name with StringValComparator and implements FieldComparator
and implement following method
class StringValComparator extends FieldComparator {
private String[] values;
private String[] currentReaderValues;
private final String field;
private String bottom;
StringValComparator(int numHits, String field) {
values = new String[numHits];
this.field = field;
}
#Override
public int compare(int slot1, int slot2) {
final String val1 = values[slot1];
final String val2 = values[slot2];
if (val1 == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return val1.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public int compareBottom(int doc) {
final String val2 = currentReaderValues[doc];
if (bottom == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return bottom.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public void copy(int slot, int doc) {
values[slot] = currentReaderValues[doc];
}
#Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field);
}
#Override
public void setBottom(final int bottom) {
this.bottom = values[bottom];
}
#Override
public String value(int slot) {
return values[slot];
}
}
Apply sorting on Fields Like
new SortField("name",new StringCaseInsensitiveComparator(), true);