How can I define new init in swift? - java

I need the code written here, I could not to paste here
https://www.geeksforgeeks.org/length-smallest-sub-string-consisting-maximum-distinct-characters/
i need it in swift

Although it's not recommended, But you can define a global constant and use it anywhere you like:
// At the top level, outside of any class or etc.
let NO_OF_CHARS = 256
Update due to question change:
C style for is deprecated in Swift (since v3 I think), you should convert the syntax to Swift like this:
/*
for (int i = 0; i < n; i++) {
}
*/
// Will be like
for i in 0...n {
}

Related

Problem binding a boolean property using a lambda [Java - JavaFX] [duplicate]

I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .

PJSUA2 Java - How to get ongoing Call's AudioMedia

I'm using the Java library for PJSUA / PJSIP and i'm trying to get the AudioMedia for an answered call but its not working. I've followed the C++ documentation (no Java doc for answering calls) which has led me to the following implementation:
public void onCallMediaState(OnCallMediaStateParam param) {
CallInfo ci = this.getInfo();
for(int i = 0; i < ci.getMedia().size(); i++) {
if(ci.getMedia().get(i).getType() == pjmedia_type.PJMEDIA_TYPE_AUDIO) {
AudioMedia aum = (AudioMedia) this.getMedia(i);
}
}
}
The first part works, it finds a media in the call info with type PJMEDIA_TYPE_AUDIO, and if i check the type of this.getMedia(i) that is also PJMEDIA_TYPE_AUDIO. However when I try to cast it to type AudioMedia it fails to cast.
I assume the rest of SIP setup is working, as when I call the number, pjsua reports the incoming call and answers it, I'm just unable to get the AudioMedia to send/receive audio.
The documentation is for C++ but thus far it has been exactly the same for Java except for this part, Reference here. What am I doing wrong?
Found it!
AudioMedia has a static method typecastFromMedia(Media media) for casting to AudioMedia. I assume this is because the casting has to occur in the underlying C++ implementation so you can't just do a high-level java cast.
Working example:
public void onCallMediaState(OnCallMediaStateParam param) {
CallInfo ci = this.getInfo();
for(int i = 0; i < ci.getMedia().size(); i++) {
if(ci.getMedia().get(i).getType() == pjmedia_type.PJMEDIA_TYPE_AUDIO) {
AudioMedia aum = AudioMedia.typecastFromMedia(this.getMedia(i));
}
}
}
You can using getAudioMedia() API to get AudioMedia, my simple onCallMediaState() in
SipCall(subclass of Call class) using C++:
void SipCall::onCallMediaState(OnCallMediaStateParam &prm) {
this->callInfo = getInfo();
unsigned media_size = this->callInfo.media.size();
for (unsigned i = 0; i < media_size; i++) {
AudioMedia audioMedia = getAudioMedia(i);
// do something
//...
}
}

Invoke Methods Dynamically on Java

At work, we have to generate a report for our client that changes its parameters several times during the week.
This report is generated from a single table on our database.
For example, imagine a table that has 100 columns and I have to generate a report with only 5 columns today, but tomorrow I have to generate with 95 of them.
With this in mind, I created a TO class with all the columns of the specified table and my query returns all columns (SELECT * FROM TABLE).
What I'm trying to create is a dynamic form to generate the report.
I first thought on create a simple frame with a list of the columns listed as check boxes and the user would select the columns that he wants (of course with a button to Select All and another to Deselect All).
As all of the columns have the same name as the attributes of the TO class, I developed the following code (I have Google this):
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
Is this the better way to do what I need to?
Thanks in advance.
Obs.: the getters of the TO class have the pattern "getAttribute_Name".
Note: This question is different from the one where the user is asking HOW to invoke some method given a certain name. I know how to do that. What I'm asking is if this is the better way to solve the problem I described.
My Java is a little more limited, but I believe that's about as good as you're going to get using reflection.
Class<?> c = Test.class;
for (String attribute : listOfAttributes) {
auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null));
}
But since this sounds like it's from potentially untrusted data, I would advise using a HashMap in this case, with each method explicitly referenced. First of all, it explicitly states what methods can be dynamically called. Second, it's more type safe, and compile-time errors are way better than runtime errors. Third, it is likely faster, since it avoids reflection altogether. Something to the effect of this:
private static final HashMap<String, Supplier<Object>> methods = new HashMap<>();
// Initialize all the methods.
static {
methods.set("Foo", Test::getFoo);
methods.set("Bar", Test::getBar);
// etc.
}
private String invokeGetter(String name) {
if (methods.containsKey(name)) {
return String.valueOf(methods.get(name).get());
} else {
throw new NoSuchMethodException();
}
}
It might sound like a major DRY violation to do so, but the repetition at least makes sure you don't wind up with unrelated getters accidentally called.
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
You can do this somewhat more elegantly via Java Beans, the Introspector, and PropertyDescriptor, but it's a little more long-winded:
Map<String, Method> methods = new HashMap<>();
Class c = this.getClass(); // surely?
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors())
{
map.put(pd.getName(), pd.getReadMethod();
}
//
for (int i = 0; i < listOfAttributes.length; i++)
{
Method m = methods.get(listOfAttributes[i]);
if (m == null)
continue;
auxText += String.valueOf(m.invoke(this, null));
}

Call functions put in array

for my code in Java I need to call functions for some figures inside a number. In fact, if my number is 464, I have to call functions named assert4 and assert6. I hope that you're understanding. But if I'm right, we can't concatenate a string and a variable to have the name of a function and execute it. For example :
for (int i = 0; i < number.length(); i++) {
assert + i + (); // For example executing the function assert4
}
So I can't see how I can do it. Thanks for help !
You can do this with reflection using something like YourClass.class.getMethod(...).invoke(...). (See this question for instance.)
However, this is a bit of a code smell and I encourage you to do something like
Map<Integer, Runnable> methods = new HashMap<>();
methods.put(464, YourClass::assert464);
...
for (int i = 0; i < number.length(); i++) {
methods.get(i).run();
}
If you're on Java 7 or older, the equivalent would be
methods.put(464, new Runnable() { public void run() { assert464(); } });
You can call a method using a String name using the reflection API.
Here's some tutorials on how to get started:
http://docs.oracle.com/javase/tutorial/reflect/
http://www.ibm.com/developerworks/library/j-dyn0603/

java: Is it possible to set a lambda expression for an array of Buttons is a for loop? If so how?

I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .

Categories

Resources