Can you equalsIgnoreCase a Set? - java

So, say I have a program, and the users target in the Set is called 'Computer'. The user enters in 'computer', 'COMPUTER','ComPutEr', but it never finds it because it's not capitalized correctly.
How would you go about taking a Set words = ... ... ... and taking the information inside of Set and checking if it is equal to 'Computer', but ignoring capitalization. Oooor! Making it so everything else is lowercase, but the first character.
Example Code:
Set<String> words= this.getConfig().getConfigurationSection("Test").getKeys(false);
if( allGroups.contains('Computer') ) {
Please ignore the this.getConfig().getConfigurationSection("Test").getKeys(false);. I am looking for an answer to fix a Minecraft plugin I'm making, but this seems like a more basic Java knowledge question.
Thank you for the help guys

You could possibly use a TreeSet because it sorts the input it can take a comparator. Using that you could implement the behaviour you want. Something like
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
}
return o1.toLowerCase().compareTo(o2.toLowerCase());
}
};
Set<String> set = new TreeSet<>(comparator);
Or (from the comments) String.CASE_INSENSITIVE_ORDER like
Set<String> set = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);

I ended up solving the problem, thanks to Elliot bringing it to my attention.
Set<String> words= new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
words.addAll(this.getConfig().getConfigurationSection("Test").getKeys(false));
args[0] = args[0].toLowerCase();
args[0] = args[0].substring(0, 1).toUpperCase() + args[0].substring(1);
if( words.contains(args[0]) ) {
Although this is not a great way of going about it in my book, I have used this same method of solving this problem with an ATM program I wrote. I'm currently thinking of a way to make the String 'args[0]' just 1 line to fix it all, but this is what currently works for me.
Thanks!

Related

Compare by multiple methods in java compareTo? [duplicate]

This question already has answers here:
How to compare objects by multiple fields
(23 answers)
Closed 3 years ago.
I don't think that's the best way to word that title but I can't think of a better way to word it. Here's my problem: I have to write a method that compares in several different ways. If the last names are the same, I then need to compare by first name. If the first names are the same, then I need to sort by section. What would be the most effective way to sort a data structure in this hierarchy? Here's what I've currently got and I think I understand why it doesn't work but I can't come up with a different way to write this function:
//Student class structure, each field has a public get/set method
public class Student implements Comparable<Student>
{
private String fname;
private String lname;
private int section;
}
//My current compareTo method
#Override
public int compareTo(Student s)
{
/*
-compare by last name
-if the same, compare by first name
-if the same, compare by section
*/
String slast = s.getLastName();
if(lname.compareTo(slast) == 0)
{
String sfirst = s.getFirstName();
if(fname.compareTo(sfirst) == 0)
{
int sclass = s.getSection();
return Integer.compare(section, sclass);
}
else
{
return fname.compareTo(sfirst);
}
}
else
{
return lname.compareTo(slast);
}
}
You can create a Comparator for your Student class this way:
Comparator<Student> comparator = Comparator
.comparing(Student::getLastName)
.thenComparing(Student::getFirstName)
.thenComparing(Student::getSection);
And then use this comparator (instead of implementing Comparable interface) to sort a list with Student objects, or to create a TreeMap with these objects:
Collections.sort(listOfStudents, comparator);
TreeMap<Student> mapOfStudents = new TreeMap<>(comparator);
You don't have to use getters or setters if you're overriding compareTo. You can also forgo the else/return statements since they're terminal return statements, and just use return.
#Override
public int compareTo(Student s) {
if (lname.compareTo(s.lname) == 0) {
if (fname.compareTo(s.fname) == 0) {
return section.compareTo(s.section);
}
return fname.compareTo(s.fname);
}
return lname.compareTo(s.lname);
}
Your code looks correct to me.
What would be the most effective way to sort a data structure in this
hierarchy?
Well, it's worth mentioning that you are potentially doing the first two comparisons (first name and last name) multiple times
if(lname.compareTo(slast) == 0)
{
//...
}
else
{
return lname.compareTo(slast);
}
It should be fairly obvious that you are doing lname.compareTo(slast) twice. You can store the result in a variable instead.
int lastNameComparison = lname.compareTo(slast);
if(lastNameComparison == 0)
{
//...
}
else
{
return lastNameComparison;
}
It is a matter of style, but I would not bother to store the result of getters into variables. Just call them when you need them.
Combining both of the above points, you get:
int lastNameComparison = lname.compareTo(s.getLastName();
if (lastNameComparison == 0)
{
int firstNameComparison = fname.compareTo(s.getFirstName());
if (firstNameComparison == 0)
{
return Integer.compare(section, s.getSection());
}
else
{
return firstNameComparison;
}
}
else
{
return lastNameComparison;
}
The nesting is quite ugly and if we need to add another criteria, it would get even worse.
We can solve that by inverting the conditions and using multiple return statements.
int lastNameComparison = lname.compareTo(s.getLastName());
if (lastNameComparison != 0) return lastNameComparison;
// Last names must be equal
int firstNameComparison = fname.compareTo(s.getFirstName());
if (firstNameComparison != 0) return firstNameComparison;
// First names must be equal
return Integer.compare(section, s.getSection());
I would personally use the declarative style of writing this, but if this code is for an assignment, that is likely not what they are expecting.

Java Collections.Sort Comparison method violates its general contract

I'm getting an error in my code since yesterday and I'm not sure why!
I googled a lot and found this Stack-Post.
I use this funtion to sort users by name and create date.
This function has worked since 2 years and now I'm getting an error for one user and I don't know what has changed.
I tried to check my data if there is anything corrupt but couldn't find anything wrong.
After reading zhe Stack-Post I still didn't understand fully what's the problem or what has changed in my project.
public void sortUsers(List<Users> sortList) {
Collections.sort(sortList, new Comparator<Users>() {
public int compare(Users user1, Users user2) {
Integer comp = 0;
comp = user1.getUsername().compareTo(user2.getUsername());
if (comp == 0) {
comp = user1.getCreateDate().before(user2.getCreateDate()) ? -1 : 1;
}
return comp;
}
});
}
comp = user1.getCreateDate().before(user2.getCreateDate()) ? -1 : 1;
This line can never return zero, in the case that the dates are equal. This means that it's not anti-symmetric (i.e. sgn(a.compareTo(b)) = -sgn(b.compareTo(a))).
The exact fix depends on what class getCreateDate() returns, but it could be something like:
comp = user1.getCreateDate().compareTo(user2.getCreateDate());
However, an easier way to do construct a compliant comparator would be:
Comparator.comparing(Users::getUsername).thenComparing(Users::getCreateDate)
or similar.

Can somebody show me a simple way to compare strings

I didn't know how to explain the question but hopefully this will make you understand
I know this code does not work
a = "hello";
if (a.equals("hello" || "greetings")){
//Execute code
}
Is there a simple way to do this without an error
I could do this but this means that i will need to repeat codes on both
a = "hello";
if (a.equals("hello")){
//Do code
}
if (a.equals("greetings")){
//Execute code
}
This is my current code but its not what i want it to do.
What i want it to do is if for example topic = "Whats the date"; i want it to execute the code because it contains date, I cant find a way to check if it contains date and so the || works
scanner = new Scanner(System.in);
String topic = scanner.nextLine();
topic = topic.toLowerCase();
if (topic.equals("time") || topic.equals("date")){
System.out.println("The time is " + Calendar.getInstance().getTime());
}
You code won't compile since the syntax is not correct in any case.
The answer is no, || operator works on boolean expressions and a String is not a boolean value.
The meaningful way to do it is the traditional way:
if (a.equals("hello") || a.equals("greetings") {
..
}
If you have many different alternatives for many different tokens then you should consider using a different approach, like a Map<String, Consumer<String>> so that you can do something like:
Map<String, Consumer<String>> mapping = new HashMap<>();
Consumer<String> greetings = s -> code;
mapping.put("hello", greetings);
mapping.put("greetings", greetings);
...
Consumer<String> mapped = mapping.get(a);
if (mapped != null)
mapped.accept(a);
if (yourString.equals("hello") || yourString.equals("greetings")){
//Execute code
}
If you want to compare your string with ignoring case. Use equalsIgnoreCase() method instead of equals()
The previous answers are correct and on point, but I'd like to change one thing just a bit:
if ("hello".equals(a) || "greetings".equals(a)) {
//...
}
That way, you are not risking NullPointerException (which would get thrown if a is null, because you can't execute a method on a null object). If you want to ignore the case, use equalsIgnoreCase(String).
Or, alternatively, use switch:
switch(a) {
case "hello": //do something
break;
case "greetings": //do something
break;
default: //handle case where there is no match, if needed
}
I found an answer to my question after some experimenting, Sorry about the confusion
scanner = new Scanner(System.in);
String topic = scanner.nextLine();
topic = topic.toLowerCase();
if (topic.contains("time") || topic.contains("date")){
System.out.println("The time is " + Calendar.getInstance().getTime());
}

Vector<Customer> C++, List<Customer> & Vector<Customer> Java

I learned this piece of code in University, while learning C++.. and I later used the same thing in C#... but now I want to use it in Java... I have looked all over Internet for similar thing, but i dun even no how to phrase it so i get the correct results.
So umm please let me know how to do this is in JAVA and also let me know what is this way called??? I know What it does.. but i have no idea how it does it.. so mind explaining it as well...
C++ is the same thing as below except one DIFFERENCE look Below
C# if (Customers[i].delExecute(delIn) == true)
C++ if (Customers[i]->delExecute(delIn) == true)
Java ?? if (????????????????????????????????)
So here I go ill try my best to explain.
C#
Class called Customer with custId etc etc
List<Customer> Customers = new List<Customers>
public void delCust(int delIn)
{
for (int i = 0; i < Customers.Count(); i++)
{
if (Customers[i].delExecute(delIn) == true)
{
Customers.Remove(Customers[i]);
break;
}
}
}
bool delExecute(int delInput) {
if (custId == delInput) {
return true;
}
return false;
}
OK right so the above code works
now I want the same thing with JAVA... anyone got any ideas how?
if (Customers.get(i).delExecute(delIn))
BTW, there is no need to say == true explicitly
In Java, Vector is an out-dated class which you should probably avoid using. Instead, you should use an ArrayList. Either way, though, both are Lists, and thus implement get for random-access.
You can implement what you're attempting as follows...
if (customers.get(i).delExecute(delIn))
Note that == true is redundant, as it is effectively an identity (true == true is true, false == true is false). You should also avoid capitalized field names in Java.
Now, there is also a preferred way to do what you are attempting using an Iterator.
private List<Customer> customers = new ArrayList<Customers>();
public void delCust(int delIn) {
final Iterator<Customer> cursor = customers.iterator();
while (cursor.hasNext()) {
if (cursor.next().delExecute(delIn)) {
cursor.remove();
break;
}
}
}
... coupled with:
boolean delExecute(int delInput) {
return custId == delInput;
}

Casting a Object to HashMap

I'm having trouble working out how to count instances of Values in a HashMap.
I have seen that there is methods attached to the Object class that look as if they are able to help me, so I've tried to cast those in to work but I must be doing something wrong somewhere.
If there's an easier way, I haven't found it yet. NB: Library is my HashMap.
public void borrowBooks(String id, String name, String sid, String sname) {
if((getKeyFromValue(Books, name).equals(id))&&(getKeyFromValue(Students, sname).equals(sid))){
if((Object)Library.countValues(sid)!=5){
Library.put(id, sid);
}
else{
System.out.println("You have exceeded your quota. Return a book before you take one out." );
}
}
}
Which doc are you looking at ? The Javadoc for Hashmap doesn't specify a countValues() method.
I think you want a HashMap<String, List<String>> so you store a list of books per student (if I'm reading your code correctly).
You'll have to create a list per student and put that into the HashMap, but then you can simply count the entries in the List using List.size().
e.g.
if (Library.get(id) == null) {
Library.put(id, new ArrayList<String>());
}
List<String> books = Library.get(id);
int number = books.size() // gives you the size
Ignoring threading etc.
First: There is (almost) no point in ever casting anything to Object. Since everything extends Object, you can always access the methods without casting.
Second: The way you're casting actually casts the return value, not the Library. If you were doing a cast that was really necessary, you would need an extra set of parentheses:
if(((Object)Library).countValues(sid) != 5)
Third: There is no countValues method in either HashMap or Object. You'll have to make your own.
This is the general algorithm to use (I'm hesitant to post code because this looks like homework):
initialize count to 0
for each entry in Library:
if the value is what you want:
increment the count
int count = 0;
for(String str : Library.values())
{
if(str == sid)
count++;
if(count == 5)
break;
}
if(count < 5)
Library.put(id, sid);
else
System.out.println("You have exceeded your quota. Return a book before you take one out." );

Categories