Categorías
Machine learning

Aprendizaje automático-Procesamiento numérico de ingeniería de características (2)

1. Recuento de procesamiento

1.1 Binarización

Establezca el número mayor o igual que un número determinado en 1, y el número menor que este número en 0
La variable de destino binario es una medida de preferencia de usuario simple y fuerte

Ejemplo: La distribución original del número de veces que escucha una canción y el número de personas es la siguiente. Se encontrará que el número original de momentos de escucha no es un fuerte indicador de las preferencias del usuario, por lo que se puede binarizar. Si el usuario ha escuchado una canción al menos una vez, entonces se considera que al usuario le gusta La canción

import pandas as pd
listen_count = pd.read_csv('millionsong/train_triplets.txt.zip',header=None, delimiter='t')# The table contains triples in the form of "user-song-number of times of listening". Only include non-zero number of listens. # Therefore, to binarize the number of listening times, just set the entire list of listening times to 1.
listen_count[2] = 1

1.1.1 Cuantificación del intervalo (binning)

La cuantificación de intervalos puede asignar valores continuos a valores discretos, que se pueden considerar como una secuencia binning ordenada, lo que representa una medición de la densidad

Para cuantificar el intervalo de datos, se debe determinar el ancho de cada ubicación. Hay dos maneras de determinar el ancho de la ubicación: contenedor de ancho fijo y ubicación adaptable

Ejemplo: Los datos sobre el número de revisiones de una empresa, el número de revisiones y la distribución del número de usuarios son los siguientes, encontrará que la mayoría de las empresas tienen un pequeño número de revisiones, pero algunas empresas tienen miles de opiniones, y el número original de revisiones abarca varios números, una solución El método es realizar la cuantificación de intervalos en el valor de recuento , y luego utilice el resultado cuantificado. En otras palabras, divida el número de revisiones en varias casillas y elimine el valor de recuento real

(1) Sub-caja de ancho fijo

Al fijar el ancho de las ubicaciones, cada ubicación contendrá un valor dentro de un rango específico. Estos rangos se pueden personalizar manualmente o generar mediante segmentación automática. Pueden ser lineales o exponenciales.

Por ejemplo, las personas se pueden dividir en rangos de edad múltiples según un período de 10 años: 0-9 años en la caja 1 y 10-19 años en la caja 2

Para asignar el valor de recuento a la ubicación, simplemente divida el valor de recuento por el ancho de la ubicación y, a continuación, tome la parte entera

Ejemplo: Cuantificación de intervalos de valores de recuento a través de ubicaciones de ancho fijo

import numpy as np
small_counts = np.random.randint(0, 100, 20)# Generate 20 random integers, uniformly distributed between 0~99
small_counts# Map to evenly spaced bins by division, and the value range of each bin is 0~9

np.floor_divide(small_counts, 10)#Map to evenly spaced bins by division, and the value range of each bin is 0~9

Cuando el valor abarca múltiples órdenes de magnitud, es mejor agruparse por la potencia de 10 (o la potencia de cualquier constante), tales como: 0-9, 10-99, 100-999, 100-999, 1000-9999

En este momento, el ancho de la bandeja aumenta exponencialmente. Para asignar el valor de recuento a la ubicación, debe tomar el logaritmo del valor de recuento. La relación entre el binning de ancho exponencial y la transformación logarítmica es muy estrecha

Ejemplo: Cuantificación de intervalos de valores de recuento a través de ubicaciones de ancho fijo

large_counts = [296, 8286, 64011, 80, 3, 725, 867, 2215, 7689, 11495, 91897,44, 28, 7971, 926, 122, 22222]# Array of count values ​​spanning several orders of magnitude

(2) Binning quantile

Si hay un gran espacio en el valor de recuento, habrá una gran cantidad de cajas vacías sin ningún dato. De acuerdo con las características de distribución de los datos, el posicionamiento adaptativo del gabinete se puede realizar utilizando el cuantilo de la distribución de datos. El cuantilo es el valor que puede dividir los datos en partes iguales, tales como: la mediana (es decir, dicotomía) dígitos), cuartiles, deciles, etc.

Ejemplo: Calcula las deciles del número de opiniones de negocios de Yelp

#Draw the deciles on the histogram
>>> deciles = biz_df['review_count'].quantile([.1, .2, .3, .4, .5, .6, .7, .8, .9])
>>> deciles
0.1 3.0
0.2 4.0
0.3 5.0
0.4 6.0
0.5 8.0
0.6 12.0
0.7 17.0
0.8 28.0
0.9 58.0

Para calcular cuantilos y asignar datos a ubicaciones cuantilo, puede utilizar la biblioteca Pandas, como se muestra en el ejemplo siguiente.

Pandas. DataFrame.quantile puede calcular el cuantilo

Pandas. Series.quantile puede calcular cuantilos

pandas.qcut puede asignar los datos al valor cuantilo requerido

Ejemplo: binning el valor de recuento por quantile

import pandas as pd # Continue to use large_couts in Example 4
pd.qcut(large_counts, 4, labels=False)# Map the count value to the quantile

# Calculate the actual quantile value
large_counts_series = pd.Series(large_counts) 
large_counts_series.quantile([0.25, 0.5, 0.75])

2. Transformación logarítmica

La función logarítmica comprime el intervalo de alto valor y amplía el intervalo de bajo valor

Ejemplo: Visualice la distribución del número de revisiones antes y después de la transformación logarítmica.

Análisis: Compara los histogramas del número de opiniones de los comerciantes de Yelp antes y después de la transformación logarítmica. Como se muestra a continuación, el eje y en ambos gráficos está en escala normal (lineal). En el gráfico siguiente, el espaciado de la caja en el intervalo (0,5, 1]es muy grande porque sólo hay 10 posibles recuentos enteros entre 1 y 10. Tenga en cuenta que el número inicial de opiniones está muy concentrado en el área de recuento bajo, pero algunos valores atípicos superaron los 4000. Después de la transformación logarítmica, la tendencia central del histograma en valores de recuento bajo se debilita, y la distribución en el eje X es más uniforme.

2.1 Demostración de transformación logarítmica

Demo de código: predecir la calificación media de un negocio utilizando el número de opiniones de Yelp después de la transformación logarítmica

# Use the Yelp review data frame to calculate the logarithmic transformation value of the number of Yelp reviews
# Note that we add 1 to the original number of reviews, so that when the number of reviews is 0, the logarithmic operation results in negative infinity. 
>>> biz_df['log_review_count'] = np.log10(biz_df['review_count'] + 1)

Demostración de código: Utilice el número de palabras después de la transformación del logaritmo en las noticias en línea datos de popularidad establecidos para predecir la popularidad del artículo

# Download the online news popularity dataset from UCI, and perform logarithmic transformation on the n_tokens_content feature. This feature represents the number of words # (token) in a news article.
>>> df['log_n_tokens_content'] = np.log10(df['n_tokens_content'] + 1)

Como se puede ver en la figura siguiente, la transformación logarítmica reorganiza el eje x. Para artículos con valores de variable de destino extremadamente grandes (>200000 recursos compartidos), la transformación logarítmica los tira más a la derecha del eje X. Para el modelo lineal, se ganó más «espacio de respiración» en el extremo bajo del espacio de entidades de entrada. Si no se realiza la transformación logarítmica (la figura superior a continuación), el modelo se enfrentará a una mayor presión y será necesario ajustarse a un valor objetivo muy grande cuando los cambios de entrada sean pequeños.

2.2 Transformación exponencial: la extensión de la transformación logarítmica

La transformación exponencial es una familia de transformaciones, y la transformación logarítmica es sólo un caso especial de ella. En términos estadísticos, todas son transformaciones de estabilización de varianza

La distribución de Poisson es una distribución de cola pesada, y su varianza es igual a su media. Por lo tanto, cuanto mayor sea su centroide, mayor será la varianza y mayor será el grado de cola pesada. La transformación exponencial puede cambiar la distribución de variables para que la varianza ya no dependa de la media

Por ejemplo, supongamos que una variable aleatoria X tiene una distribución de Poisson. Si lo transformas tomando su raíz cuadrada, la varianza de su raíz cuadrada es aproximadamente una constante, en lugar de igual a la media.

La siguiente figura muestra una representación aproximada de la distribución de Poisson, que es un ejemplo de una distribución donde la varianza aumenta con la media. Muestra la influencia de λ en la distribución de Poisson, y λ representa el valor medio de la distribución de Poisson. Cuando λ se hace más grande, no sólo todo el patrón de distribución cambia a la derecha, sino que la calidad está más dispersa, y la varianza se hace más grande.

Tanto la transformación de la raíz cuadrada como la transformación logarítmica se pueden generalizar fácilmente a la transformación de Box-Cox

La siguiente figura muestra la transformación Box-Cox cuando λ = 0 (transformación logarítmica), λ = 0,25, λ = 0,5 (una forma de escala y traducción de transformación de raíz cuadrada), λ = 0,75 y λ = 1,5. Cuando λ es menor que 1, el valor de gama alta se puede comprimir; cuando λ es mayor que 1, el efecto es opuesto.

La fórmula Box-Cox solo es válida cuando los datos son positivos. Para los datos no positivos, podemos agregar una constante fija para cambiar los datos.

Demo de código: Transformación de Box-Cox del número de opiniones de los comerciantes de Yelp

>>> from scipy import stats
# Following the previous example, suppose biz_df contains Yelp business review data.
# Box-Cox transformation assumes that the input data are all positive.
# Check the minimum value of the data to make sure that the assumption is met.
>>> biz_df['review_count'].min()
3
# Set the input parameter λ to 0 and use logarithmic transformation (without fixed-length displacement).
>>> rc_log = stats.boxcox(biz_df['review_count'], lmbda=0)
# By default, SciPy will find the λ parameter that makes the output closest to the normal distribution when it implements the Box-Cox conversion. 
>>> rc_bc, bc_params = stats.boxcox(biz_df['review_count'])
>>> bc_params
-0.4106510862321085

A continuación se muestra el histograma del número de críticas de los comerciantes de Yelp después de la transformación de Box-Cox (abajo), así como el histograma del número de opiniones iniciales (superior) y el histograma del número de comentarios después de la transformación de logaritmo (medio)

El gráfico de probabilidad es un método de visualización muy simple para comparar la distribución real y la distribución teórica de los datos. Es esencialmente un gráfico de dispersión que muestra la relación entre el cuantilo medido y el cuantilo teórico.

La siguiente figura muestra dos gráficos de probabilidad de los datos de revisión de Yelp. Son los gráficos de probabilidad del número inicial de revisiones y el número de revisiones después de la transformación, y en comparación con la distribución normal.

Debido a que los datos observados deben ser positivos, y la distribución gaussiana puede ser negativa, es imposible que el cuantilo medido y el cuantilo teórico coincidan en el lado negativo. Por lo tanto, sólo nos centramos en la parte positiva. Por lo tanto, podemos ver que en comparación con la distribución normal, el número inicial de revisiones tiene características obvias de cola pesada. (El valor ordenado puede alcanzar más de 4000, pero el cuantilo teórico sólo puede alcanzar aproximadamente 4.) Tanto la transformación logarítmica ordinaria como la transformación óptima de Box-Cox pueden acercar la cola positiva a la distribución normal.

Se puede ver claramente en el gráfico que la transformación óptima de Box-Cox comprime la cola con más fuerza que la transformación logarítmica. Hace que la cola se aplane y corre por debajo de la isolina roja.

3. Escala/normalización de características

Algunos valores de entidad están delimitados, como longitud y latitud

Pero algunas características numéricas se pueden aumentar sin límite, como el valor de recuento

Algunos modelos son funciones fluidas de entrada, como modelos de regresión lineal, modelos de regresión logística o modelos que contienen matrices, y se ven afectados por la escala de entrada.

Por el contrario, a esos modelos basados en árboles no les importa cuán grande sea la escala de entrada.

Si el modelo distingue a la escala de las entidades de entrada, se requiere el escalado de entidades.

El escalado de características cambiará la escala de características, algunas personas llaman a it normalización de características

El escalado de entidades se realiza normalmente de forma independiente para cada entidad

Escala de 3,1 min-max

Deje que x sea un valor de entidad independiente (es decir, el valor de entidad en un determinado punto de datos), min(x) y max(x) son los valores mínimos y máximos de esta entidad en todo el conjunto de datos, respectivamente. El escalado min-max puede comprimir (o expandir) todos los valores de eigen en el [0, 1] Intervalo

La fórmula para el escalado min-max es la siguiente:

3.2 escala de estandarización/varianza de características

Estandarización de entidades: primero resta el valor medio de la entidad (para todos los puntos de datos) y, a continuación, se divide por la varianza, por lo que también se denomina escalado de varianza. El valor medio de la operación escalada es 0 y la desviación es 1. Si la característica inicial obedece a la distribución gaussiana, la característica a escala también obedece a la distribución gaussiana.

La fórmula para la estandarización de entidades es la siguiente:


3.3 ρ 2 rho^2 Ρ2Normalizado

Esta técnica de normalización consiste en dividir el valor eigen inicial por un valor llamado ρ 2 rho^2 Ρ2La cantidad de norma, ρ 2 rho^2 Ρ2La norma también se llama norma euclidiana, y se define de la siguiente manera:

ρ 2 rho^2 Ρ2La norma es una medida de la longitud de un vector en el espacio de coordenadas. Su definición puede derivarse del famoso teorema pitágoras (dada la longitud de dos lados angulares rectos de un triángulo en ángulo recto, se puede encontrar la longitud de la hipotenusa):

La norma primero suma el cuadrado del valor de la entidad en todos los puntos de datos y, a continuación, calcula la raíz cuadrada. Pasar por ρ 2 rho^2 Ρ2 Después de la normalización, la norma de la columna de entidades es 1

Independientemente del método de escalado utilizado, el escalado de entidades siempre divide la entidad por una constante (denominada constante de normalización). Por lo tanto, no cambia la forma de la distribución de una sola operación

Demostración de código: ejemplo de escalado de características

# Load online news popularity data set
>>> df = pd.read_csv('OnlineNewsPopularity.csv', delimiter=', ')
# View the original data-the number of words in the article
>>> df['n_tokens_content'].as_matrix()
array([ 219., 255., 211., ..., 442., 682., 157.])
# min-max zoom
>>> df['minmax'] = preproc.minmax_scale(df[['n_tokens_content']]) >>> df['minmax'].as_matrix()
array([ 0.02584376, 0.03009205, 0.02489969, ..., 0.05215955,0.08048147,  0.01852726])
# Standardization-Note that according to the definition of standardization, some results will be negative
>>> df['standardized'] = preproc.StandardScaler().fit_transform(df[['n_tokens_ content']])
>>> df['standardized'].as_matrix()
array([-0.69521045, -0.61879381, -0.71219192, ..., -0.2218518 ,0.28759248, -0.82681689])
# L2-Normalization
>>> df['l2_normalized'] = preproc.normalize(df[['n_tokens_content']], axis=0) 
>>> df['l2_normalized'].as_matrix()
array([ 0.00152439, 0.00177498, 0.00146871, ..., 0.00307663, 0.0047472 ,  0.00109283])

La siguiente figura muestra el número de palabras en el artículo de noticias original y ampliado. Tenga en cuenta que solo ha cambiado la escala del eje X y la forma de la distribución a escala de entidades permanece sin cambios

Cuando las escalas de un conjunto de entidades de entrada son muy diferentes, se requiere el escalado de entidades. Por ejemplo, un sitio web comercial popular puede tener cientos de miles de visitas diarias, mientras que el comportamiento real de compra puede ser sólo unos pocos miles de veces. Si el modelo utiliza ambas entidades, el modelo debe equilibrar la escala antes de decidir cómo utilizarlas. Si la escala de las entidades de entrada es muy diferente, causará problemas de estabilidad numérica para el algoritmo de entrenamiento del modelo. En este caso, las características deben estandarizarse.

4. Características interactivas

El producto de dos características puede formar un par de características interactivas simples

Esta relación de multiplicación se puede comparar con el operador lógico AND, que puede expresar el resultado formado por un par de condiciones: «El comportamiento de compra proviene de la zona con el código postal 98121» Y «El usuario tiene entre 18 y 35 años».

Ejemplo: Los pares de características interactivas del conjunto de datos de popularidad de noticias en línea de UCI se utilizan para predecir el número de artículos de noticias compartidas.

>>> from sklearn import linear_model
>>> from sklearn.model_selection import train_test_split
>>> import sklearn.preprocessing as preproc
# Assuming df is a Pandas data frame, which contains UCI online news popularity data set >>> df.columns
Index(['url', 'timedelta', 'n_tokens_title', 'n_tokens_content',
            'n_unique_tokens', 'n_non_stop_words', 'n_non_stop_unique_tokens','num_hrefs', 'num_self_hrefs', 'num_imgs', 'num_videos',
            'average_token_length', 'num_keywords', 'data_channel_is_lifestyle',
            'data_channel_is_entertainment', 'data_channel_is_bus',
            'data_channel_is_socmed', 'data_channel_is_tech',
            'data_channel_is_world', 'kw_min_min', 'kw_max_min', 'kw_avg_min',
            'kw_min_max', 'kw_max_max', 'kw_avg_max', 'kw_min_avg', 'kw_max_avg',
            'kw_avg_avg', 'self_reference_min_shares', 'self_reference_max_shares',
            'self_reference_avg_sharess', 'weekday_is_monday', 'weekday_is_tuesday',
            'weekday_is_wednesday', 'weekday_is_thursday', 'weekday_is_friday',
            'weekday_is_saturday', 'weekday_is_sunday', 'is_weekend', 'LDA_00',
            'LDA_01', 'LDA_02', 'LDA_03', 'LDA_04', 'global_subjectivity',
            'global_sentiment_polarity', 'global_rate_positive_words',
            'global_rate_negative_words', 'rate_positive_words',
            'rate_negative_words', 'avg_positive_polarity', 'min_positive_polarity',
            'max_positive_polarity', 'avg_negative_polarity',
            'min_negative_polarity', 'max_negative_polarity', 'title_subjectivity',
            'title_sentiment_polarity', 'abs_title_subjectivity',
            'abs_title_sentiment_polarity', 'shares'],
           dtype='object')
# Select content-related features as the single features of the model, and ignore those derived features 
>>> features = ['n_tokens_title','n_tokens_content','n_unique_tokens', 'n_non_stop_words', 'n_non_stop_unique_tokens','num_hrefs', 'num_self_hrefs', 'num_imgs', 'num_videos', 'average_token_length','num_keywords','data_channel_is_lifestyle','data_channel_is_entertainment', 'data_channel_is_bus', 'data_channel_is_socmed', 'data_channel_is_tech', 'data_channel_is_world']
>>> X = df[features]
>>> y = df[['shares']]
# Create an interactive feature pair, skip the fixed offset item
>>> X2 = preproc.PolynomialFeatures(include_bias=False).fit_transform(X) >>> X2.shape
(39644, 170)
# Create training set and test set for two feature sets
>>> X1_train, X1_test, X2_train, X2_test, y_train, y_test = train_test_split(X, X2, y, test_size=0.3, random_state=123)
>>> def evaluate_feature(X_train, X_test, y_train, y_test):
     ...     """Fit a linear regression model on the training set and
     ...     score on the test set"""
     ...     model = linear_model.LinearRegression().fit(X_train, y_train)
     ...     r_score = model.score(X_test, y_test)
     ...     return (model, r_score)
# Train the model on two feature sets and compare R-square scores
>>> (m1, r1) = evaluate_feature(X1_train, X1_test, y_train, y_test)
>>> (m2, r2) = evaluate_feature(X2_train, X2_test, y_train, y_test) 
>>> print("R-squared score with singleton features: %0.5f" % r1) 
>>> print("R-squared score with pairwise features: %0.10f" % r2) 
R-squared score with singleton features: 0.00924
R-squared score with pairwise features: 0.0113276523

Nota:

La construcción de características interactivas es muy simple, pero es caro de usar. Si el modelo lineal contiene pares de entidades interactivos, su tiempo de entrenamiento y tiempo de puntuación aumentarán de O(n) a O(n2), donde n es el número de entidades individuales

Hay varias maneras de omitir el costo computacional de las características interactivas de alto orden. Podemos realizar la selección de características después de construir todas las características interactivas, o podemos diseñar un pequeño número de características complejas con más cuidado.

5. Selección de características

La tecnología de selección de características puede optimizar las características inútiles para reducir la complejidad del modelo final. Su objetivo final es obtener un modelo simplificado, que puede aumentar la velocidad de cálculo sin reducir la precisión de la predicción o tener poco efecto en la precisión de la predicción.

La selección de características no es para reducir el tiempo de entrenamiento, sino para reducir el tiempo de puntuación del modelo

Las técnicas de selección de entidades se pueden dividir en las tres categorías siguientes:

(1) Filtro

La tecnología de filtrado preprocesa las entidades para eliminar aquellas entidades que es poco probable que sean útiles para el modelo. Por ejemplo, podemos calcular la correlación o la información mutua entre cada entidadd la variable de respuesta y, a continuación, filtre aquellas entidades que están por debajo de un determinado umbral. El costo de las técnicas de filtrado es mucho menor que las técnicas de embalaje descritas a continuación, pero no consideran el modelo que queremos utilizar, por lo que es posible que no puedan seleccionar las características correctas para el modelo. Lo mejor es utilizar cuidadosamente las técnicas de prefiltrado para evitar eliminar involuntariamente características útiles antes de entrar en la etapa de entrenamiento del modelo.

(2) Método de embalaje

Estas tecnologías son muy costosas, pero pueden experimentar con varios subconjuntos de características, lo que significa que no eliminaremos accidentalmente características que no proporcionan mucha información por sí mismas, sino que son muy útiles en combinación con otras características. El método de empaquetado trata el modelo como una caja negra que puede dar una puntuación razonable al subconjunto de características recomendado. Utilizan otro método para optimizar iterativamente el subconjunto de entidades.

(3) Método integrado

Este método utiliza la selección de entidades como parte del proceso de entrenamiento del modelo. Por ejemplo, la selección de entidades es una función inherente de los árboles de decisión, ya que selecciona una entidad para dividir el árbol en cada etapa de entrenamiento. Otro ejemplo es el término regular l1, que se puede agregar al objetivo de entrenamiento de cualquier modelo lineal. l1 El término regular anima al modelo a utilizar menos características en lugar de más características, por lo que también se denomina restricción de espasmos del modelo. Los métodos integrados integran la selección de características como parte del proceso de formación del modelo. No son tan potentes como el método de embalaje, pero el costo no es tan alto como el método de embalaje. En comparación con las técnicas de filtrado, los métodos incrustados pueden seleccionar entidades que son especialmente adecuadas para un determinado modelo. En este sentido, el método integrado logra un cierto equilibrio entre el coste computacional y la calidad del resultado.

Referencia:
«Competente en ingeniería de largometrajes» Alice Zheng Amanda Casali
Pensamientos rotos de los niños pequeños

Terminado el 21 de noviembre de 2020

.

Categorías
Otros

Patrón de diseño Java-17, implementación de patrones de intérprete de lenguaje personalizado

Capítulo 17: Modo intérprete-Implementación del lenguaje personalizado

Definición:

Modo intérprete(Patrón de intérprete): defina la gramática de un idioma y cree un intérprete para interpretar las oraciones en el idioma. Aquí, «idioma» se refiere al código utilizando el formato y la gramática prescritos.

Explicar la expresión y, a continuación, calcular

Estructura:

imagen-2020111201641245

Código:

//Abstract expression
abstract class AbstractExpression {
    public abstract void interpret(Context ctx);
}
//Terminal expression
class TerminalExpression extends AbstractExpression {
    public void interpret(Context ctx) {
        //Explanation operation of terminal expression
    }
}
//Non-terminal expression: contains two operation elements
class NonterminalExpression extends AbstractExpression {
    private AbstractExpression left;
    private AbstractExpression right;

    public NonterminalExpression(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    public void interpret(Context ctx) {
        //Recursively call the interpret() method of each component
        //Specify the connection mode of the components during the recursive call, that is, the function of non-terminal symbols
    }
}
//Environment category, store global information
class Context {
    private HashMap map = new HashMap();

    public void assign(String key, String value) {
        //Set a value in the environment class
    }

    public String lookup(String key) {
        //Get the value stored in the environment class
        return null;
    }
}

Aplicaciones:

Programa de control de robots, muévete de acuerdo con el entorno de instrucción

Reglas gramaticales

expression ::= direction action distance | composite //expression
composite ::= expression 'and' expression //Compound expression
direction ::= 'up' | 'down' | 'left' | 'right' //Movement direction
action ::= 'move' | 'run' //Movement method
distance ::= an integer //Moving distance

1 + 2 + 3 – 4 + 1

expression ::= value | operation
operation ::= expression '+' expression | expression '-' expression
value ::= an integer //An integer value

Árbol de sintaxis

imagen-2020111201523048

Utilice el modo intérprete para lograr

imagen-20201112202433601

imagen-20201112202535199

Función de contexto

Entrar

LOOP 2 
	 PRINT Yang Guo SPACE SPACE PRINT Little Dragon Girl
BREAK END 
	 PRINT Guo Jing SPACE SPACE PRINT Huang Rong

Reglas gramaticales:

expression ::= command* //Expression, an expression contains multiple commands
command ::= loop | primitive //Statement command
loop ::= 'loopnumber' expression 'end' //Loop command, where number is a natural number
primitive ::= 'printstring' | 'space' | 'break' //Basic command, where string is a string

imagen-20201112205344914

//Environmental category: used to store and manipulate statements that need to be explained. In this example, each word that needs to be explained can be called an action mark (Action
class Context {
    private StringTokenizer tokenizer; //StringTokenizer class, used to decompose strings into smaller
    private String currentToken; //Current string mark

    public Context(String text) {
        tokenizer = new StringTokenizer(text); //Create StringTokenizer through the incoming command string
        nextToken();
    }

    //Return to the next mark
    public String nextToken() {
        if (tokenizer.hasMoreTokens()) {
            currentToken = tokenizer.nextToken();
        } else {
            currentToken = null;
        }
        return currentToken;
    }

    //Return the current mark
    public String currentToken() {
        return currentToken;
    }

    //Skip a mark
    public void skipToken(String token) {
        if (!token.equals(currentToken)) {
            System.err.println("Error message:" + currentToken + "The explanation is wrong!");
        }
        nextToken();
    }

    //If the current mark is a number, return the corresponding value
    public int currentNumber() {
        int number = 0;
        try {
            number = Integer.parseInt(currentToken); //Convert a string to an integer
        } catch (NumberFormatException e) {
            System.err.println("Error message:" + e);
        }
        return number;
    }
}
//Abstract node class: abstract expression
abstract class Node {
    public abstract void interpret(Context text); //Declare a method to explain the statement

    public abstract void execute(); //Declare a method to execute the command corresponding to the mark
}
//Expression node class: non-terminal expression
class ExpressionNode extends Node {
    private ArrayList<Node> list = new ArrayList<Node>(); //Define a set to store multiple tags

    public void interpret(Context context) {
        //Loop processing the tags in the Context
        while (true) {
            //If there is no mark, exit the explanation
            if (context.currentToken() == null) {
                break;
            }
            //If it is marked as END, then do not explain END and end this explanation process, you can continue the explanation after
            else if (context.currentToken().equals("END")) {
                context.skipToken("END");
                break;
            }
            //If it is another tag, explain the tag and add it to the command set
            else {
                Node commandNode = new CommandNode();
                commandNode.interpret(context);
                list.add(commandNode);
            }
        }
    }

    //Circularly execute each command in the command set
    public void execute() {
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            ((Node) iterator.next()).execute();
        }
    }
}
//Statement command node class: non-terminal expression
class CommandNode extends Node {
    private Node node;

    public void interpret(Context context) {
        //Processing LOOP loop commands
        if (context.currentToken().equals("LOOP")) {
            node = new LoopCommandNode();
            node.interpret(context);
        }
        //Process other basic commands
        else {
            node = new PrimitiveCommandNode();
            node.interpret(context);
        }
    }

    public void execute() {
        node.execute();
    }
}
//Cyclic command node class: non-terminal expression
class LoopCommandNode extends Node {
    private int number; //Cycles
    private Node commandNode; //Expression in loop statement

    //Explain the loop command
    public void interpret(Context context) {
        context.skipToken("LOOP");
        number = context.currentNumber();
        context.nextToken();
        commandNode = new ExpressionNode(); //Expression in loop statement
        commandNode.interpret(context);
    }

    public void execute() {
        for (int i = 0; i < number; i++)
            commandNode.execute();
    }
}
//Basic command node class: terminator expression
class PrimitiveCommandNode extends Node {
    private String name;
    private String text;

    //Explain the basic commands
    public void interpret(Context context) {
        name = context.currentToken();
        context.skipToken(name);
        if (!name.equals("PRINT") && !name.equals("BREAK") && !name.equals("SPACE")) {
            System.err.println("Illegal order!");
        }
        if (name.equals("PRINT")) {
            text = context.currentToken();
            context.nextToken();
        }
    }

    public void execute() {
        if (name.equals("PRINT"))
            System.out.print(text);
        else if (name.equals("SPACE"))
            System.out.print(" ");
        else if (name.equals("BREAK"))
            System.out.println();
    }
}
class Client {
    public static void main(String[] args) {
        String text = "LOOP 2 PRINT Yang Guo SPACE SPACE PRINT Little Dragon Girl BREAK END PRINT Guo Jing SPACE SPACE PRINT Huang Rong";
        Context context = new Context(text);
        Node node = new ExpressionNode();
        node.interpret(context);
        node.execute();
    }
}

imagen-20201112211825221

Ventaja:

  1. Fácil de cambiar y ampliar la gramática. Puesto que las clases se utilizan para representar las reglas gramaticales del lenguaje en el modo de intérprete, la gramática se puede cambiar o ampliar a través de mecanismos como la herencia.
  2. Cada regla gramatical se puede expresar como una clase, por lo que un lenguaje simple se puede implementar fácilmente.
  3. Es más fácil implementar la gramática. La implementación de cada clase de nodo de expresión en el árbol de sintaxis abstracta es similar, el código de estas clases no es especialmente complicado y el código de clase de nodo puede ser generado automáticamente por algunas herramientas.
  4. Es más conveniente agregar nuevas expresiones de explicación. Si el usuario necesita agregar una nueva expresión de interpretación, solo necesita agregar una nueva expresión de terminal o una clase de expresión no terminal. El código de clase de expresión original no necesita ser modificado y se ajusta al «principio de apertura y cierre».

Desventajas:

  1. Es difícil mantener una gramática compleja. En el modo de intérprete, cada regla debe definir al menos una clase. Por lo tanto, si un idioma contiene demasiadas reglas gramaticales, el número de clases aumentará bruscamente, lo que dificultará la gestión y el mantenimiento del sistema. En este momento, puede considerar el uso de un programa de análisis de sintaxis, etc. Forma de reemplazar el modo de intérprete.
  2. La eficiencia de ejecución es baja. Dado que un gran número de bucles y llamadas recursivas se usan en el modo de intérprete, es muy lento al interpretar oraciones más complejas y el proceso de depuración del código también es más problemático.

Escena aplicable:

  1. Una oración de un lenguaje que necesita ser interpretada y ejecutada se puede representar como un árbol de sintaxis abstracto.
  2. Algunos problemas recurrentes se pueden expresar en un lenguaje sencillo.
  3. La gramática de un lenguaje es relativamente simple.
  4. La eficiencia de ejecución no es un problema clave.

.

Categorías
Python

Colección Python

                                                                                                  Operation of Python collections

Un conjunto es una secuencia desordenada de elementos que no se repiten. Los elementos de la colección son inmutables
El propósito de la colección es almacenar diferentes valores juntos. Se utilizan diferentes colecciones para operaciones relacionales, sin tener que preocuparse por un único valor de la colección.

1. Crear una colección

#Create collection directly
name0 = {1,2,3,'Hello there','luatao'}
print(name0)
#Use the constructor set() to create a collection
name1 = set() #Create empty collection
print(name1)
#Create a collection using a list
name2 = ['nihoa',1,2]
name3 = set(name2)
print(name3)

Resultado de la salida:

{1, 2, 3, ‘Hola’, ‘luatao’}
set()
{‘nihoa’, 1, 2}

2. Configurar para eliminar la duplicación

#Create collection directly
name0 = {1,2,3,'Hello there',2,3,'luatao'}
print('Original collection:',name0)

Resultado de la salida:

Conjunto original: {‘luatao’, 1, 2, 3, ‘Hola’}

3. Visite la colección

Los elementos almacenados en la colección están desordenados y no repetitivos, por lo que no puede tener acceso a los elementos almacenados en la colección a través de índices como listas y tuplas. El acceso a los elementos de colección puede usar el operador miembro en o no para determinar si un elemento está en la colección.

#Create collection directly
name0 = {1,2,3,'Hello there','luatao'}

print('luatao' in name0)#true
print('luatao' not in name0)#false

Resultado de la salida:

Verdad
Falso

4. Añadir elementos

Agregue el elemento x al conjunto s, si el elemento ya existe, no haga nada.

#Create collection directly
name0 = {1,2,3,'Hello there','luatao'}
print('Original collection:',name0)
#Add a single element
name0.add('luatao')#Elements exist without any operation
name0.add('nihao')#Element does not exist, join the collection
print('Current collection:',name0)
#Add multiple elements List, tuple, dictionary are all the same
name0.update((2,'ada'))#Add a tuple
print('Current collection:',name0)
name0.update((2,'ada'),(3,4,5))#Add two tuples
print('Current collection:',name0)

Resultado de la salida:

Conjunto original: {1, 2, 3, ‘luatao’, ‘hello’}
Conjunto actual: {1, 2, 3, ‘luatao’, ‘hello’, ‘nihao’}
Conjunto actual: {1, 2, 3, ‘luatao’, ‘ada’, ‘hello’, ‘nihao’}
Conjunto actual: {1, 2, 3, 4, 5, ‘luatao’, ‘ada’, ‘hello’, ‘nihao’}

5. Eliminar elementos

#Create collection directly
name0 = {1,2,3,'Hello there',2,3,'luatao'}
print('Original collection:',name0)

name0.remove('luatao')#Remove luatao does not exist, an error will occur
print('remove:',name0)

name1 = {1,2,3,'Hello there',2,3,'luatao'}
name1.discard('luatao')#Remove luatao does not exist, no error will occur
print('discard:',name1)

name2 = {1,2,3,'Hello there',2,3,'luatao'}
name2.pop()#Randomly remove an element from the set
print('pop:',name2)

name3 = {1,2,3,'Hello there',2,3,'luatao'}
name3.clear()#Delete all elements in the collection
print('clear:',name3)

Resultado de la salida:

Conjunto original: {1, 2, 3, ‘luatao’, ‘hello’}
eliminar: {1, 2, 3, ‘Hola’}
descarte: {1, 2, 3, ‘Hola’}
pop: {2, 3, ‘luatao’, ‘hello’}
claro: set()

6. Establecer operaciones

Intersección, unión, complemento, subconjunto, superconjunto

#Create collection directly
name0 = {1,2,3,'a','b','c'}
name1 = {2,3,4,'b','c'}
print('Original collection name0:',name0)
print('Original collection name1:',name1)
#Intersection &
name3 = name0 & name1
print('Intersection:',name3)#name0 has it, name1 has it
#  |
name4 = name0 | name1
print('Union:',name4)#All elements
#Complement -
name5 = name0 - name1
print('Complement:',name5)#name0 has but name1 does not
#Symmetrical complement ^
name6 = name0 ^ name1
print('Symmetric complement:',name6)#name0 has but name1 does not have and name1 does not have name0 has
# >
#  <
print('Superset:',name0>name1)# Ture name0 is a superset of name1
print('Subset:',name0<name1)#false name0 is not a subset of name1

#Set equality ==
#Collection of unequal !=
print('equal:',name0 == name1)#false
print('Wait:',name0 != name1)#true

Resultado de la salida:

El nombre original del conjunto0: {1, 2, 3, ‘a’, ‘b’, ‘c’}
El nombre original del conjunto1: {2, 3, 4, ‘b’, ‘c’}
Intersección: {‘b’, ‘c’, 2, 3}
Unión: {1, 2, 3, ‘a’, 4, ‘b’, ‘c’}
Complemento: {1, ‘a’}
Complemento simétrico: {4, 1, ‘a’}
Superconjunto: Falso
Subconjunto: False
Igual: Falso
varía: Verdadero

7. Colecciones inmutables

El problema con las colecciones anidadas es que las colecciones normalmente no pueden contener valores variables como colecciones. En este caso, es posible que desee utilizar un conjunto inmutable (conjunto congelado). Excepto que el valor no se puede cambiar, los conjuntos inmutables y los conjuntos mutables son muy similares. Puede utilizar «frozenset()» para crear un conjunto inmutable.

name0 = frozenset()#Create an empty fixed collection
print(name0)
name1 = frozenset([1,2,3,4])#Use iterable objects to create a fixed collection
print(name1)

Resultado de la salida:

frozenset()
frozenset({1, 2, 3, 4})
Es importante recordar que una de las principales desventajas de los conjuntos inmutables es que son inmutables, lo que significa que no puede agregarles elementos ni eliminar elementos de ellos. .

8. Funciones integradas de la colección

Método Descripción
set.add(elmnt) El método add() se utiliza para agregar elementos a la colección. Si el elemento agregado ya existe en la colección, no se realiza ninguna operación.
set.clear() El método clear() se utiliza para eliminar todos los elementos de la colección.
set.copy() El método copy() se utiliza para copiar una colección.
set.difference(set) El método difference() se utiliza para devolver la diferencia del conjunto, es decir, los elementos de conjunto devueltos están contenidos en el primer conjunto, pero no en el segundo conjunto (parámetro del método).
set.difference_update(set) El método difference_update() se utiliza para quitar los elementos que existen en ambos conjuntos. La diferencia entre el método difference_update() y el método difference() es que el método difference() devuelve una nueva colección con los mismos elementos quitados, mientras que el método difference_update() quita directamente los elementos de la colección original sin devolver un valor.
set.discard(valor) El método discard() se utiliza para quitar el elemento de colección especificado. Este método es diferente del método remove() porque el método remove() causará un error al quitar un elemento inexistente, mientras que el método discard() no lo hará.
set.remove(item) El método remove() se utiliza para quitar el elemento especificado en la colección. Este método es diferente del método discard() porque el método remove() causará un error al quitar un elemento inexistente, mientras que el método discard() no lo hará.
set.pop() El método pop() se utiliza para eliminar aleatoriamente un elemento.
set.update(set) El método update() se utiliza para modificar la colección actual. Puede agregar nuevos elementos o colecciones a la colección actualIon. Si el elemento agregado ya existe en la colección, el elemento solo aparecerá una vez y los duplicados se omitirán.
set.union(set1, set2…) El método union() devuelve la unión de los dos conjuntos, es decir, contiene todos los elementos del conjunto y los elementos repetidos solo aparecerán una vez.
set.intersection(set1, set2 … etc.) El método intersection() se utiliza para devolver los elementos contenidos en dos o más conjuntos, es decir, la intersección.
set.intersection_update(set1, set2 … etc.) El método intersection_update() se utiliza para obtener elementos que se superponen en dos o más conjuntos, es decir, para calcular la intersección. El método intersection_update() es diferente del método intersection(), porque el método intersection() devuelve un nuevo conjunto, mientras que el método intersection_update() quita elementos no superpuestos del conjunto original.
set.symmetric_difference(set) El método symmetric_difference() devuelve una colección de elementos únicos en las dos colecciones, es decir, quita los elementos que existen en ambas colecciones.
set.symmetric_difference_update(set) El método symmetric_difference_update() quita los mismos elementos en otro conjunto especificado en el conjunto actual e inserta elementos diferentes en otro conjunto especificado en el conjunto actual.
set.isdisjoint(set) El método isdisjoint() se utiliza para determinar si dos conjuntos contienen los mismos elementos, si no, devuelve True, de lo contrario devuelve False. .
set.issubset(set) El método issubset() se utiliza para determinar si todos los elementos de la colección se incluyen en la colección especificada, si es así, devuelve True, de lo contrario devuelve False.
set.issuperset(set) El método issuperset() se utiliza para determinar si todos los elementos de la colección especificada están contenidos en la colección original, si es así, devuelve True, de lo contrario devuelve False.
name0 = {1,2,'a','b,','luatao',3.3,'Lu Atao'}
print('Initial collection:',name0)

name0.add('ds') #Add a 5, if it already exists, do not execute
print('add:',name0)

name0.clear()#Empty elements
print('clear:',name0)

name1 = {1,2,'a','b,','luatao',3.3,'Lu Atao'}
name2 = name1.copy()#copy
print('copy:',name2)

name3 = {1,2,3}
name4 = {2,3,4}
print('difference:',name3.difference(name4))# name3-name4

name5 = {1,2,3,4,5,6}
name6 = {2,3,4,1}
name5.difference_update(name6)
print('difference_update:',name5)#Remove elements contained in both sets

name7 = {2,3,4,1}
name7.discard(4)#Delete 4
print('discard:',name7)#

name8 = {2,3,4,1}
name8.remove(4)#Delete 4
print('remove:',name8)#

name9 = {2,3,4,1}
x = name9.pop()#Randomly delete an element
print('The pop-up value:',x)
print('pop:',name9)#

name10 = {2,3,4,1}
name11 = ['nihoa','Hello there',3,4,5]
name10.update(name11)#Add name11 to name10
print('update:',name10)#

name12 = {1,2,'a'}
name13 = {1,3,4,'b'}
name14 = {3,4,'c'}
name15 = name12.union(name13)#Two sets merge
print('union:',name15)
name16 = name12.union(name13,name14)#Three sets merge
print('union:',name16)

name17 = {1,2,'a'}
name18 = {1,3,4,'b'}
name19 = {3,4,'c'}
name20 = name17.intersection(name18)#Two sets intersect
print('intersection:',name20)
name21 = name17.intersection(name18,name19)#Three sets of intersection
print('intersection:',name21)

name22 = {1,2,'a'}
name23 = {1,3,4,'b'}
name24 = {3,4,'c',1}
name22.intersection_update(name23)#Two sets intersect
print('intersection_update:',name22)
name22.intersection_update(name23,name24)#Three sets of intersection
print('intersection_update:',name22)

name25 = {1,2,3,4,5,6}
name26 = {2,3,4,1}
name27 = name25.symmetric_difference(name26)
print('symmetric_difference:',name27)#Remove elements contained in both sets

name28 = {1,2,3,4,5,6}
name29 = {2,3,4}
name28.symmetric_difference_update(name29)
print('symmetric_difference_update:',name28)#Remove the duplicate elements in the original set x and the y set, and insert the non-repeated elements into the set x:

name30 = {1,2,3,4,5,6}
name31 = {2,3,4}
name32 = name30.isdisjoint(name31)#Does not contain return true contains contains returns false
print('isdisjoint:',name32)#Judging whether there is an element in the set y that contains the set x:

name33 = {1,2,3,4,5,6}
name34 = {2,3,4}
name35 = name33.issubset(name34)#Both contain return true, otherwise return false
print('issubset:',name35)#Judge whether all elements of set x are included in set y:

name36 = {1,2,3,4,5,6}
name37 = {2,3,4}
name38 = name36.issuperset(name37)#Both contain return true, otherwise return false
print('issuperset:',name38)#Judge whether all elements of set y are included in set x:

Resultado de la salida:

Conjunto inicial: {1, 2, 3.3, ‘luatao’, ‘a’, ‘b’, ‘Luatao’}
añadir: {1, 2, 3.3, ‘luatao’, ‘ds’, ‘a’, ‘b’, ‘Luatao’}
claro: set()
copia: {1, 2, 3.3, ‘b’, ‘Lu Atao’, ‘luatao’, ‘a’}
diferencia: {1}
difference_update: {5, 6}
descarte: {1, 2, 3}
eliminar: {1, 2, 3}
Valor emergente: 1
pop: {2, 3, 4}
actualización: {1, 2, 3, 4, 5, ‘nihoa’, ‘hello’}
unión: {1, 2, 3, 4, ‘b’, ‘a’}
unión: {1, 2, 3, 4, ‘a’, ‘c’, ‘b’}
intersección: {1}
intersección: set()
intersection_update: {1}
intersection_update: {1}
symmetric_difference: {5, 6}
symmetric_difference_update: {1, 5, 6}
isdisjoint: Falso
issubset: Falso
issuperset: Verdadero

Después de comer, vine a escribir y trabajé más de una hora. Sudando profusamente, espero que valga la pena.

.

Categorías
Java

(Java) El expression y el caso «remember login user name»

1 Visión general básica de las expresiones de EL

Las expresiones EL (Express Lanuage) se pueden incrustar en páginas jsp para reducir la escritura de scripts jsp. El propósito de EL es reemplazar la escritura de scripts de salida <%= data%> en páginas jsp.

2 Formato y función de la expresión EL

El formato de la expresión EL:

${EL expression content}

El papel de la expresión EL:

  1. DeObjeto de dominioPara encontrar los datos especificados.
  2. Uso de objetos integrados de EL
  3. Operador de ejecución

3 Uso básico de expresiones EL (recuperar datos del dominio)

  • EL obtiene un cierto valor de cuatro dominios:${key}
    • Alcance de la acciónDe pequeño a grandeEs para obtener atributos del dominio pageContext, el dominio de solicitud, el dominio de sesión y el dominio de aplicación a su vez. Después de obtenerlo en un determinado dominio, no mirará hacia atrás.
    • Entre ellos, si solo desea obtener el valor en el campo pageContext:${pageScope.key}
    • Entre ellos, si solo desea obtener el valor en el campo de solicitud:${requestScope.key}
    • Entre ellos, si solo desea obtener el valor en el campo de sesión:${sessionScope.key}
    • Entre ellos, si solo desea obtener el valor en el dominio de aplicación:${applicatioScope.key}

3.1 Obtener datos ordinarios a través de expresiones EL

  • Formato:
${key}
  • De esta manera, EL busca la clave en el orden de menor a mayor de los cuatro dominios, y la genera si la encuentra, y no continúa buscándola. Consulte el siguiente ejemplo para obtener más información.

Demostración de código:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Get the data in the domain container</title>
</head>
<body>
    <%
        // 1 save the data in the domain container
        pageContext.setAttribute("city", "Beijing 1"); // page
        pageContext.setAttribute("city", "Beijing 2", PageContext.REQUEST_SCOPE); // request
        pageContext.setAttribute("city", "Beijing 3", PageContext.SESSION_SCOPE); // session
        pageContext.setAttribute("city", "Beijing 4", PageContext.APPLICATION_SCOPE); // servletContext

        // 2 delete the specified domain data
        /*
        pageContext.removeAttribute("city", PageContext.PAGE_SCOPE); // page
        pageContext.removeAttribute("city", PageContext.REQUEST_SCOPE); // request
        pageContext.removeAttribute("city", PageContext.SESSION_SCOPE); // session
        pageContext.removeAttribute("city", PageContext.APPLICATION_SCOPE); // servletContext
         */
        pageContext.removeAttribute("city"); // Delete data in all domains
    %>

    <h1>java</h1>
        <h3>retrieve data</h3>
        <%
            out.print(pageContext.getAttribute("city")!=null?pageContext.getAttribute("city"):""); // page
            out.print(pageContext.getAttribute("city", PageContext.REQUEST_SCOPE)); // request
            out.print(pageContext.getAttribute("city", PageContext.SESSION_SCOPE)); // session
            out.print(pageContext.getAttribute("city", PageContext.APPLICATION_SCOPE)); // servletContext
        %>

        <h3>Get data intelligently</h3>

        <%
            /*
                         pageContext.findAttribute(key) Get data from the four domain containers in turn according to the key, if it is obtained, the value ends; if it is not obtained, return null
             */
            out.print(pageContext.findAttribute("city"));
        %>

    <h1>EL</h1>
        <h3>retrieve data</h3>
        ${pageScope.city}
        ${requestScope.city}
        ${sessionScope.city}
        ${applicationScope.city}

    <h3>Get data intelligently</h3>  <%--The most commonly used is this--%>
        ${city} 
</body>
</html>

3.2 EL obtiene el valor del objeto javaBean

Formato:

${Object. Member Variable}

Suponiendo que User es un objeto javaBean:

public class User {
    private String username;
    private String password;
    private String nickname;
    //Omit construction method, get, set method
}

Demostración de código:

<%@ page import="cn.itcast.pojo.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        // EL gets the value of the javaBean object
        User user = new User();
        user.setUsername("zhangsan");
        user.setPassword("abc");
		// Placed in the request field, because the EL expression can only get the data in the field
        request.setAttribute("user", user);  
    %>
	
	<%--The most general java statement, generally not used--%>
    <h1>java</h1>
    username = <%=((User)pageContext.findAttribute("user")).getUsername()%> <br/>
    password = <%=((User)pageContext.findAttribute("user")).getPassword()%> <br/>
    nickname = <%=((User)pageContext.findAttribute("user")).getNickname()%>

    <hr/>

	<%--ELSentence acquisition, the most commonly used, and the simplest--%>
    <h1>EL</h1>
        username === ${user.username} <br/>
        password === ${user.password} <br/>
        nickname === ${user.nickname} <br/>
</body>
</html>

3.3 Adquisición de ELList<String>Valor de

Formato:

${List collection object[index]}

Demo de código

<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
    ELExpression role one(Get data from the domain): ELGet List<String>  Value of

         format: ${  List collection object[index] }
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--1.Create List<String>set,  Store in the Request field --%>
    <%
        List<String> list = new ArrayList<String>();
        list.add("Reba");
        list.add("Naza");
        request.setAttribute("list",list);
    %>

    <%--2.byELexpression,  Get List<String>Data in the collection--%>
    <%--Obtained by jsp, not recommended--%>
    <%
        List<String> names = (List<String>) request.getAttribute("list");
        out.print( names.get(0) +" === "+ names.get(1) );
    %>
    <%--ELWay to get--%>
    ${list[0]} == ${list[1]}

</body>
</html>

[External link image transfer failed. The origin site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-eEgMw0t8-1606008306083)(day08_jsp&filter&listener.assets/1568520799607.png)]

3.4 Adquisición de ELList<User>Valor de

Formato:

${List collection object[index]. member variable}

Demo de código

<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.itheima.pojo.User" %><%--
    ELExpression role one(Get data from the domain): ELGet List<User>  Value of

         format: ${  List collection object[index].Member variables  }
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--1.Create List<User>set,  Store in the Request field --%>
    <%
        List<User> list = new ArrayList<User>();
        list.add(new User("Reba","123456"));
        list.add(new User("Naza","abcdef"));
        request.setAttribute("list",list);
    %>

    <%--2.byELexpression,  Get List<User>Data in the collection--%>
    <%--Jsp method to obtain--%>
    <%
        List<User> users = (List<User>) request.getAttribute("list");
        out.print( users.get(0).getUsername() +"=="+ users.get(0).getPassword() );
        out.print( users.get(1).getUsername() +"=="+ users.get(1).getPassword() );
    %>
    <br/>
    <%--ELWay to get--%>
    ${list[0].username} == ${list[0].password}
    ${list[1].username} == ${list[1].password}

</body>
</html>

Salida:

3.5 EL obtiene el valor de Mapa<Cadena,Usuario>

Formato:

${Map collection object.key. member variable}
 Or
 ${Map collection object['key']. member variable}

Demo de código

<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="com.itheima.pojo.User" %>
<%@ page import="java.util.Map" %><%--
    ELExpression role one(Get data from the domain): ELGet Map<String, User>  Value of

         format:
        ${Map collection object.key.Member variables  }
                 Or
        ${Map collection object['key'].Member variables}
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--1.Create Map<String, User>set,  Store in the Request field --%>
    <%
        Map<String, User> userMap = new HashMap<String, User>();
        userMap.put("user1", new User("Reba","123456"));
        userMap.put("user2", new User("Naza","abcdef"));
        request.setAttribute("userMap",userMap);
    %>

    <%--2.byELexpression,  Get Map<String, User>Data in the collection--%>
    <%--Jsp method is not recommended--%>
    <%
        Map<String, User> map = (Map<String, User>) request.getAttribute("userMap");
        out.print( map.get("user1").getUsername() +"=="+ map.get("user1").getPassword());
        out.print( map.get("user2").getUsername() +"=="+ map.get("user2").getPassword());
    %>
    <br/>
    <%--ELWay to obtain, generally use the first way--%>
    ${userMap.user1.username} == ${userMap.user1.password}
    ${userMap.user2.username} == ${userMap.user2.password}
    <br/>
    ${userMap['user1'].username} == ${userMap['user1'].password}
    ${userMap['user2'].username} == ${userMap['user2'].password}

</body>
</html>

4 Página de objetos integrada de ELContext

  • pageContext: El objeto de contexto de la página en el desarrollo web.

Función: se puede utilizar para obtener datos en los cuatro dominios de JSP (pageScope, requestScope, sessionScope, applicationScope)

  • Por ejemplo, en Servlet, desea obtener el nombre de la aplicación web:request.getContextPath();
  • A continuación, en la página jsp, quiero obtener el nombre de la aplicación web:${pageContext.request.contextPath}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Get the name of the WEB application project</title>
</head>
<body>
    <h3>Get the name of the WEB application project</h3>
         <%--Get by JSP--%>
    <%= request.getContextPath()%>
         <%--Get by EL method--%>
    ${pageContext.request.contextPath}
</body>
</html>

5 Operador de ejecución EL (entender)

  1. Operadores aritméticos +,-, *, /,%
  2. Operadores lógicos &&, ||,!
  3. Operadores de comparación>, <, >=, <=, ==, !=
  4. Operador nulo vacío
  5. Operador ternario

Demostración de código:

<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>ELExecution operator</title>
</head>
<body>
    ${3+4} <br>
    ${3-4} <br>
    ${true&&true} <br>
    ${false&& true} <br>
    ${3>4} <br>
    ${3<4 || 5>4} <br>

    <%--Save data to the domain,  Used to demonstrate empty--%>
    <%
        String str = null;
        request.setAttribute("str", str);
        request.setAttribute("array", new String[1] );
        request.setAttribute("list", new ArrayList<String>());
    %>
    ${empty str} <br>
    ${empty array} <br>
    ${empty list} <br>

    ${str == null?"Data is empty":str} <br>

</body>
</html>

Salida:

6 Caso Registre el nombre de usuario utilizado para el último inicio de sesión

  1. Descripción del problema
    En la interfaz de inicio de sesión, si se introduce el nombre de usuario y la contraseña, y recuerda que el nombre de usuario está marcado, después de hacer clic en iniciar sesión, el nombre de usuario se rellenará automáticamente cuando se abra la página de inicio de sesión la próxima vez.
  2. Análisis de pasos:
    (1) Obtener el nombre de usuario y la contraseña enviados
    (2) Obtenga si desea «recordar el nombre de usuario»
    (3) Determinar si el nombre de usuario y la contraseña coinciden con la base de datos: si coinciden, redirigir a la página de inicio; si no coinciden, reenvíe de nuevo a la página de inicio de sesión, solicitando que el nombre de usuario o contraseña sea incorrecto; al mismo tiempo, siempre y cuando se compruebe el nombre de usuario remember, la cookie El valor del nombre de usuario. Se muestra en la página
  3. Implementación:
    (1) La dirección de envío del formulario de inicio de sesión es Servlet
    (2) En el Servlet, después de obtener el nombre de usuario y la contraseña, compare con los datos de la base de datos y vaya a la página correspondiente para el éxito o el error
    (3) Determine si el botón recordar nombre de usuario está marcado en el formulario extraído. Si es así, almacene el nombre de usuario en una cookie, consigalo y muénstrelo en la página de inicio de sesión.
  4. La racionalidad de poner el nombre de usuario en la cookie:
    Si se colocan en el servidor, los datos no se pueden obtener cuando se actualiza o se repara el servidor.
  • Mire la interfaz de inicio de sesión primerologin.jspCódigo:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>log in</title>
</head>
<body>
<%--Note here, the way to get the submission path--%>
<form action="${pageContext.request.contextPath}/login" method="post">
    <table>
        <tr>
            <td>username</td>
            <%--Pay attention here-How to get the input value-%>
            <td><input type="text" name="username" value="${cookie.user.value}"/></td>
        </tr>
        <tr>
            <td>password</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="checkbox" name="rem" value="remUsername">  Remember Account Name</td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="submit"></td>
        </tr>
    </table>
</form>
</body>
</html>

  • Echemos un vistazo al código Servlet procesado
package servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
   * Handle the operation of remembering the user name
   * 1. Authentication of user name and password
   * 2. Record the user name
 */
@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. Get username and password
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 2. Judgment
        if (username.equals("tom") && password.equals("1234")){
            //login successful
            response.getWriter().write("login success");

        }else {
            // Login failed
            request.setAttribute("message","Login failed! Username or password is wrong, please re-enter");
            // forward to the login page
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }

        // Get whether remember user name is checked in the form, if checked, the user name will be stored in the cookie
        String rem = request.getParameter("rem");
        if (rem != null){
            // Checked Remember username
            Cookie cookie = new Cookie("user",username);
            cookie.setMaxAge(60*10*24*10); //Remember for 10 days
            cookie.setPath(request.getContextPath());
            response.addCookie(cookie);
        }

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

.

Categorías
Otros

La línea de comandos más completa y sencilla del historial de mysql para agregar usuarios, modificar permisos, modificar las operaciones básicas de ip de permisos de inicio de sesión, etc.

1. Agregar usuarios

1.1  Login MYSQL:

  @>mysql -u root -p

  @>Password

Crear usuario:

   Format:CREATE USER 'username'@'host' IDENTIFIED BY 'password';
    username-the username you will create description:

	 host-Specify the host on which the user can log in, if it is a local user, localhost can be used, if you want the user to log in from any remote host, you can use the wildcard%
	 Example:
	CREATE USER 'javacui'@'localhost' IDENTIFIED BY '123456'; 
 
	CREATE USER 'javacui'@'172.20.0.0/255.255.0.0' IDENDIFIED BY '123456'; 
	 
	CREATE USER 'javacui'@'%' IDENTIFIED BY '123456'; 
	 
	CREATE USER 'javacui'@'%' IDENTIFIED BY ''; 
	 
	CREATE USER 'javacui'@'%';
	
	 password-the user's login password,Password can be empty,If it is empty, the user can log in to the server without a password

Autorización(Debe crear un usuario antes de poder autorizar, la autorización directa notificará un error)

        format:GRANT privileges ON databasename.tablename TO 'username'@'host';

Privilegios -Los permisos de funcionamiento del usuario, como SELECT, INSERT, UPDATE, etc. (consulte el final de este artículo para obtener la lista detallada). Si desea conceder los permisos, utilice las instrucciones ALL:

Databasename – nombre del almacenamiento de datos

Tablename -Nombre de tabla, si desea conceder al usuario los permisos de operación correspondientes en todas las bases de datos y tablas, puede utilizar * para indicar, como *.*

Por ejemplo:

	AuthorizationSELECT,INSERT
   GRANT SELECT, INSERT ON test.user TO 'javacui'@'%'; 
   
     Authorization to query, insert, modify, delete permissions
   GRANT SELECT, INSERT, UPDATE, DELETE ON test.user TO 'javacui'@'%'; 
   
 	  Grant all permissions ALL
	GRANT ALL ON *.* TO 'javacui'@'%';
	
    FLUSH PRIVILEGES;
    
  #Note: "localhost" here means that the user can only log in locally and cannot log in remotely on another machine.  
  #If you want to log in remotely, change "localhost" to "%",   
  # Means that you can log in on any computer. You can also specify that a certain machine can log in remotely.

Nota: El usuario autorizado por el comando anterior no puede autorizar a otros usuarios. Si desea que se autorice al usuario, utilice el siguiente comando

GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;

Revocar permisos de usuario

REVOKE privileges ON databasename.tablename FROM 'username'@'host';

Descripción del ejemplo: privilege, databasename, tablename-same como parte de autorización

REVOKE SELECT ON *.* FROM 'javacui'@'%';

2. Modifique la contraseña

método uno:
Establecer y cambiar la contraseña de usuario

SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');

Si actualmente ha iniciado sesión en el usuario

SET PASSWORD = PASSWORD("newpassword");

Método dos:

useUPDATEDirect edituserTable

  mysql -u root -p password

  mysql> use mysql;

  mysql> UPDATE user SET Password = PASSWORD('newpass') WHERE user = 'root';

  mysql> FLUSH PRIVILEGES;


 When you lose the root password, you can do this

  mysqld_safe --skip-grant-tables&

  mysql -u root -p 
  
  mysql> use mysql;

  mysql> UPDATE user SET password=PASSWORD("new password") WHERE user='root';

  mysql> FLUSH PRIVILEGES;

3. Modifique el IP de inicio de sesión para que ese IP pueda iniciar sesión

método uno:

Change the table method.

 It may be that your account does not allow remote login, only localhost. At this time, as long as the computer on localhost, after logging in mysql, change "mysql"  In the database "user"  External "host"  Items from"localhost"Renamed"%"

mysql -u root -p

mysql>use mysql;

mysql>update user set host = '%' where user = 'root';

mysql>select host, user from user;

Método dos:

Authorization law.

 For example, if you want myuser to use mypassword to connect to the mysql server from any host.

GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;

FLUSH PRIVILEGES;

 If you want to allow the user myuser to connect to the mysql server from the host whose ip is 192.168.1.6, and use mypassword as the password

GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'192.168.1.3' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;

FLUSH PRIVILEGES;

 If you want to allow the user myuser to connect to the dk database of the mysql server from the host whose ip is 192.168.1.6, and use mypassword as the password

GRANT ALL PRIVILEGES ON dk.* TO 'myuser'@'192.168.1.3' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;

FLUSH PRIVILEGES;

Para modificar el ip de inicio de sesión, consulte másLa base de datos se puede conectar de forma remota o se puede acceder a ella con una dirección IP

4. Eliminar usuario

  @>mysql -u root -p

  @>Password

   mysql>Delete FROM user Where User='test' and Host='localhost';

   mysql>flush privileges;

   mysql>drop database testDB; //Delete the user's database

 Delete account and permissions:
		 >drop user  username@'%';

      >drop user  [email protected]; 

5. Enumere todas las bases de datos

  mysql>show database;

6. Cambiar la base de datos

	mysql>use 'data storage name';

7. Enumere todas las tablas

  mysql>show tables;

8. Mostrar la estructura de la tabla de datos

  mysql>describe  Table Name;

9. Elimine la base de datos y la tabla de datos

  mysql>drop database  data storage name;

  mysql>drop table  Data table name;

10. Operaciones de mesa

Construir una tabla

      Remarks: Use "use <data storage name>"Should connect to a database.
   Command:create table <Table Name> (<Field name 1> <Types of  1> [,..<Field name n> <Type n>]);
    Example:
  mysql> create table MyClass(                 
  > id int(4) not null primary key auto_increment,      
  > name char(20) not null,               
  > sex int(4) not null default '0',            
  > degree double(16,2));               

Obtener la estructura de la mesa

  Command: desc  Table name, orshow columns from  Table Name 
    Example:
  mysql> describe MyClass        
  mysql> desc MyClass;             
  mysql> show columns from MyClass;     

Eliminar tabla

  Command:drop table <Table Name>
    For example: delete the table named MyClass
  mysql> drop table MyClass;

Insertar datos

  Command:insert into <Table Name> [( <Field name 1>[,..<Field name n > ])] values (  Value 1 )[, (  Value n )]
    Example:
  mysql> insert into MyClass values(1,'Tom',96.45),(2,'Joan',82.99), (2,'Wang', 96.59);

Consultar los datos de la tabla

 Query all rows
  mysql> select * from MyClass;

Consultar las primeras filas de datos

   For example: view the front of the table MyClass 2  Row data
  mysql> select * from MyClass order by id limit 0,2;
    or
  mysql> select * from MyClass limit 0,2;

Eliminar los datos de la tabla

  Command:delete from  Table Name  where  Expression
    For example: delete the number in the table MyClass 1  record of 
  mysql> delete from MyClass where id=1;

Modificar los datos de la tabla

  Command:update  Table Name  set  Field=New value,... where  Condition
  mysql> update MyClass set name='Mary' where id=1;

Añadir campos a la tabla

  Command:alter table  Table Name  add  Field Type Other;
    For example: add a field passtest to the table MyClass,Type is int(4),The default value is 0
  mysql> alter table MyClass add passtest int(4) default '0'

Cambiar el nombre de la tabla

  Command:rename table  Original table name to  New table name;
    For example: Change the name of MyClass to YouClass in the table
  mysql> rename table MyClass to YouClass;

Actualizar el contenido del campo

  Command:update  Table Name  set  Field name =  New content
  update  Table Name  set  Field name = replace(Field name, 'Old content', 'New content');
    For example: add before the article 4  Spaces
  update article set content=concat('    ', content);

.

Categorías
Otros

Directrices para citas en documentos

Bienvenido a la gasolinera Xiaobai de investigación donde estudias duro~

Referencias en los periódicos

Al hacer investigaciones científicas, me referiré a algunos otros documentos (revistas, conferencias, libros, páginas web). Al escribir un documento, debe marcar las citas en el contenido correspondiente y escribir el contenido relevante de las citas al final del texto.

¿Cómo escribir el contenido de la literatura citada al final del artículo? Esto implicaFormato y contenidoDos preguntas.

El formato de los documentos citados está generalmente determinado por el objeto de la presentación. Las publicaciones periódicas, revistas, etc. tienen sus propios formatos prescritos. (En la actualidad, sólo aprendí el formato de cita IEEE, y continuaré actualizando otros formatos en el futuro ^ _ ^)

El contenido de los documentos citados generalmente debe ser revisado por nosotros.

A continuación, presentaré desde los dos aspectos de formato y contenido ~

Cita del IEEE

Citando diferentes tipos de documentos, el formato sigue siendo diferente.

Formato

  • Formato del diario de referencia en el documento:


Composición: Autor, Título del artículo» Título de la revista (Debe ser abreviado), número de volumen, número de emisión, número de página, año.

  • Formato de conferencia de referencia en el documento:

    Composición: Autor, «Título del papel» Nombre de la conferencia (Debe ser abreviado), Ciudad de conferencias, País: Editor de volúmenes, Año, Número de página.

  • **Referencia al formato arXiv en el papel:

    Composición: Autor, «Título del papel» arXiv preimpresión arXiv:

Una vez claro el formato, necesitamos consultar la información relevante del documento de referencia y rellenar la plantilla de formato.

Para ver la información pertinente del documento, generalmente usoEspejo de Google.


Puede encontrar información relevante.

Si la información aquí no está completa, también podemos hacer clic en

Puede encontrar información más completa buscando la palabra cita en el sitio web.

Consejos:
Si se publica un documento citado en el IEEE, primero puede consultarlo en este sitio web
https://www.engineeringvillage.com/search/quick.url


Primero consulta el título, haz clic en el detalle anterior, puedes ver mucha información

Si necesita exportar algunos archivos de referencia (.bib), haga clic en el cuadro rojo de la figura anterior y aparecerá

Listo para descargar~

Utilice el documento .bib para cargar el contenido del documento citado y, a continuación, compilarlo en Látex para obtener el formato de cita, o ponerlo en mendeley y luego cite el papel en la palabra incrustado en el complemento mendely. Todos estos métodos son buenos, y puedes grabarlo en tu propio blog posterior.

Ahora entendamos primero.archivo bibSi instala estas referencias~

Referencias en archivos .bib

  • Periódico
@article{lin2020modeling,
author = {Lin, Dan and Wu, Jiajing and Yuan, Qi and Zheng, Zibin},
journal = {IEEE Trans. Circuits Syst. II Express Briefs},
publisher = {IEEE},
title = {{Modeling and understanding {E}thereum transaction records via a complex network approach}},
volume={67},  
number={11},  
pages={2737-2741},
year = {2020}
}
  • Reunión
@inproceedings{remy2017tracking,
  title={{T}racking {B}itcoin users activity using community detection on a network of weak signals},
  author={Remy, Cazabet and Rym, Baccour and Matthieu, Latapy},
  booktitle={Proc. Int. Conf. Complex Networks their Appl. },
  pages={166--177},
  year={2017},
  publisher={Springer},
  address={Lyon, France }
  • Libro
@book{DBLP:books/ox/Newman10,
  author    = {Mark E. J. Newman},
  title     = {Networks: An Introduction},
  publisher = {Oxford University Press},
  year      = {2010},
}
  • Sitio web
@misc{2019Ethereum,
  title={Ethereum{ETL}},
  note =  {{P}ython scripts for etl},
  howpublished ="https://github.com/blockchain-etl/ethereum-etl",
  year={2019},
}

Es más conveniente organizar los documentos citados en archivos Bib y convertirlos en el contenido de citas al final del documento.

En el archivo BIB, bajo el formato IEEE,Hay algunas reglas para el uso de letras mayúsculas

  1. Mayúsculas al principio del título (no es necesario añadir {}), si hay sustantivos adecuados en el título ({B}itcoin, {E}thereum, etc.), la primera letra de esta palabra debe estar en mayúsculas y usar {} para enmarcar las letras mayúsculas. La función de {} es mantener el formato de la letra, sin {}, la letra que se muestra al final sigue siendo minúscula.
  2. Otros lugares, como publisher={{IEEE}}, donde cada IEEE necesita ser capitalizado, por lo que el todo debe ser encajonado {}.

Encontrar abreviaturas

En conferencias y revistas, tanto el booktitle como el diario deben abreviarse. A continuación, presentaré algunos métodos convenientes para obtener abreviaturas.
Tabla de búsqueda de abreviatura del IEEE
Guía de referencia del IEEE



Por supuesto, no hay abreviaturas para todas las palabras.

Por lo tanto, hay otra manera de encontrar abreviaturas

Usa mendeley para encontrar abreviaturas
En primer lugar, importe el archivo de documento (.bib o .ris) en mendeley
En segundo lugar, haga clic en Ver–Estilo de cita–Abreviaturas de diario…

Por último, habrá

Sólo tiene que encontrar la abreviatura correspondiente ~

(Para continuar)

.

Categorías
Otros

Patrón de diseño-patrón singleton

Introducción

Asegúrese de que solo hay una instancia de una clase, crear una instancia de ella misma y proporcionar esta instancia al sistema

El método de construcción no puede ser público
Esta instancia es una variable miembro de clase de la clase actual

Lograr

De acuerdo con el tiempo de creación de instancias, se puede dividir en estilo hambriento y estilo perezoso.

  1. Estilo chino hambriento: crea una instancia cuando se carga la clase
public class Singleton {
    private Singleton(){}
    private static Singleton singleton = new Singleton();  //Hungry Chinese

    public synchronized static Singleton getInstance(){
        return singleton;
    }


    public static void main(String[] args) {
    	System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
    }
}
  1. Estilo perezoso: no cree una instancia cuando se cargue la clase, sino que la crea una instancia cuando se utilice por primera vez. Preste atención a la seguridad de los hilos.
public class Singleton {
    private Singleton(){}
    private static Singleton singleton;

    public synchronized static Singleton getInstance(){ //Thread safe
        if(singleton == null){    //Determine whether to instantiate
            singleton = new Singleton();
        }
        return singleton;
    }


    public static void main(String[] args) {
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
    }
}

Usamos bloqueo de subprocesos para bloquear todo el método de esta manera afectará al rendimiento, porque nuestro propósito es crear instancias del códigonew Singleton();Sólo ejecútelo una vez. Después de crear instancias una vez, no habrá más creación de instancias, pero en este momento se ejecutará el método de sincronización, lo que afecta al rendimiento, por lo que usamosFragmento de código de sincronizaciónPara garantizar la seguridad de la rosca y mejorar la velocidad de retorno. A saber: doble bloqueo de comprobación.

public class Singleton {
    private Singleton(){}
    private volatile static Singleton singleton;  //******

    public static Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton.class) {
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }


    public static void main(String[] args) {
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
    }
}

singletonObjeto a utilizarvolatileModificación para evitar la reordenación

Excepción

2 situaciones en las que se generan varias instancias
Hay varias máquinas virtuales Java en un sistema distribuido y cada máquina virtual tiene una instancia.
Se utilizan varios cargadores de clases en la misma máquina virtual para generar varias instancias.

Además, el modo singleton es generalmente apátrida y se proporciona en forma de herramientas.

.

Categorías
Otros

1115 Contando nodos en un idioma BST (30 puntos)-C PAT Clase A

1115 Nodos de recuento en un BST (30 puntos))

Un árbol de búsqueda binario (BST) se define recursivamente como un árbol binario que tiene las siguientes propiedades:

  • El subárbol izquierdo de un nodo solo contiene nodos con claves inferiores o iguales a la clave del nodo.
  • El subárbol derecho de un nodo solo contiene nodos con claves mayores que la clave del nodo.
  • Los subárboles izquierdo y derecho también deben ser árboles de búsqueda binarios.

Inserte una secuencia de números en un árbol de búsqueda binario inicialmente vacío. A continuación, se supone que debe contar el número total de nodos en los 2 niveles más bajos del árbol resultante.

Especificación de entrada:

Cada archivo de entrada contiene un caso de prueba. Para cada caso, la primera línea proporciona un entero positivo N (≤1000) que es el tamaño de la secuencia de entrada. A continuación, dado en la siguiente línea son los enteros N en [−1000,1000] que se supone que se insertan en un árbol de búsqueda binario inicialmente vacío.

Especificación de salida:

Para cada caso, imprima en una línea el número de nodos en los 2 niveles más bajos del árbol resultante en el formato:

n1 + n2 = n

donde n1 es el número de nodos en el nivel más bajo, n2 es el del nivel anterior, y n es la suma.

Entrada de muestra:

9
25 30 42 16 20 20 35 -5 28

Salida de muestra:

2 + 4 = 6

Idea principal:

Escriba N nodos, inserte un árbol de búsqueda binario,

Genere el número de las dos últimas capas de nodos n1, n2 y su suma n1 + n2 = n

Ideas de diseño:
  • Lectura de datos mientras se construye un árbol de búsqueda binario
  • Una vez completado el establecimiento, vuelva a atravesar, registre el número de cada capa y la capa más profunda máx.
  • Generar el número de las dos últimas capas
Compilador: C (gcc)
include <stdio.h>
#include <stdlib.h>

struct node {
        int d;
        struct node *left, *right;
};

struct node *build(struct node *root, int d)
{
        if (root == NULL) {
                root = (struct node *)malloc(sizeof(struct node));
                root->d = d;
                root->left = NULL;
                root->right = NULL;
        } else if (d <= root->d) {
                root->left = build(root->left, d);
        } else {
                root->right = build(root->right, d);
        }
        return root;
}

int level[1010] = {0}, maxdepth = 0;

void dfs(struct node *root, int depth)
{
        if (root == NULL) {
                maxdepth = maxdepth > depth ? maxdepth :depth;
                return ;
        }
        level[depth]++;
        dfs(root->left, depth + 1);
        dfs(root->right, depth + 1);
}

int main(void)
{
        int n, t;
        struct node *root = NULL;

        scanf("%d", &n);
        while (n--) {
                scanf("%d", &t);
                root = build(root, t);
        }
        dfs(root, 0);
        printf("%d + %d = %d", level[maxdepth - 1], level[maxdepth - 2], level[maxdepth - 1] + level[maxdepth - 2]);
        return 0;
}

.

Categorías
Java

Parámetro de ejecución del threadpool Java (multiproceso) que significa

idea principal: Se ejecutan un total de 20 tareas, el número de subprocesos principales es 4, el número máximo de subprocesos principales es 10, actualmente se agregan 20 ejecutables (equivalente a 20 tareas),

Es necesario ejecutar 20 tareas, pero el número de subprocesos principales es solo 4 y hay 16 tareas. Dado que la cola De LinkedBlockingQueue es
El número máximo de tareas que se pueden almacenar es 10. Cuando la cola esté llena, se creará un nuevo subproceso para ejecutar la tarea. En este momento, el número máximo de subprocesos es 10.
Todavía hay 6 LinkedBlockingQueues no básicos. En este momento, se abrirán 6 subprocesos para ejecutarse. Actualmente, el número máximo de subprocesos es 10.
Todavía hay 10 en la cola en este momento. Sólo tiene que cumplir con el tamaño de la cola (Almacene primero en la cola De LinkedBlockingQueue, almacene el resto para crear un nuevo subproceso

package com.zkdj.urlCheck.spring_boot_1.main.java.controller.thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import lombok.NonNull;

public class ThreadController {

	private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(4, Math.min(CPU_COUNT - 1, 5));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 2;
    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(10);
	private static ThreadPoolExecutor THREAD_POOL_EXECUTOR;

 //A total of 20 tasks are executed, the number of core threads is 4, the maximum number of core threads is 10, currently 20 runnables are added (equivalent to 20 tasks),
   //20 tasks need to be executed, but the number of core threads is only 4, and there are 16 tasks, because the LinkedBlockingQueue queue is
 //The maximum number of tasks stored is 10. When the queue is full, a new thread will be created to execute the task. At this time, the maximum thread is 10. 
 //There are still 6 non-core LinkedBlockingQueues. At this time, 6 threads will be opened to execute. Currently, the maximum number of threads is 10,
 //There are still 10 in the queue at this time. Just meet the size of the queue

    static {
                 System.out.println("Core thread count=" + CORE_POOL_SIZE);
                 System.out.println("Maximum number of threads=" + MAXIMUM_POOL_SIZE);

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                                 CORE_POOL_SIZE, //Number of core threads
                                 MAXIMUM_POOL_SIZE, //The maximum number of threads in the thread pool
                                 60, //The survival time of the thread, when there is nothing to do, the idle time
                                 TimeUnit.SECONDS, //Unit of thread survival time
                                 sPoolWorkQueue, //Thread cache queue
                                 new ThreadFactory() {//Thread creation factory, if the thread pool needs to create a thread, newThread will be called to create it
                    @Override
                    public Thread newThread(@NonNull Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setDaemon(false);
                        return thread;
                    }
                });
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                                         System.out.println("Execution completed" + Thread.currentThread().getName());
                }

            };
                         //Throw it to the thread pool for execution
            THREAD_POOL_EXECUTOR.execute(runnable);
        }
    }
}

.

Categorías
Otros

Trucos CSS

CSS, al igual que HTML, también es un lenguaje de marcado. El código también es muy simple. También debe ser interpretado y ejecutado por un navegador. También se puede escribir con cualquier editor de texto. Su extensión de archivo es «. CSS».

  • Funciones principales del CSS

La función principal de CSS es embellecer la página y separar el contenido y la apariencia de la página (similar al maquillaje, cirugía plástica^^).

   🐏  🐏  🐏  🐏  🐏  🐏  🐏  🐏  🐏  🐏  🐏  🐏


Instrucciones

Estilo en línea, estilo en línea

Formato:

<Label name style="CSS code">
                 The first code!
</Label name>

Ejemplo:

	<p style="color: blue;">
        First code
    </p>

Nudo:
En este caso, el color del texto «primera línea de código» en p se convertirá en azul.

Estilo interno

Formato

 <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
                 CSS code
    </style>
</head>

Ejemplo:

	<style>
        p{
            color: blue;
        }
    </style>

Nudo:
En este caso, el color del texto en p se convertirá en azul.

Estilo exterior

Crear un archivo CSS independiente, utilizar la etiqueta de vínculo en la etiqueta de cabecera html para introducir, estos dos últimos son condiciones opcionales
Formato:

<link href="CSS file path" type="text/CSS" rel="stylesheet">

Ejemplo:

<link rel="stylesheet" type="text/CSS" href="../CSS/First lesson.CSS">

Aquí usted necesita crear un archivo CSS fuera

p{
    color: blue;
}

Nudo:
Ahora agregue las condiciones en el archivo css, y el color de la etiqueta p también ha cambiado a azul.

Método de importación

Lo mismo que el método de enlace, pero algunos navegadores no se pueden utilizar, por lo que no se utiliza comúnmente, sólo entender
Formato

    <style>
        @import url("The path to import the CSS file");

    </style>

css archivo sin cambios

Sintaxis básica del CSS

Las reglas CSS constan de dos partes principales:Selector y una o varias declaraciones.

selector{declaration1;declaration2… declaraciónN}

El selector suele ser el elemento html del estilo que necesita cambiar. El selector incluye muchas formas, todas las etiquetas html se pueden utilizar como selectores, como la tabla de cuerpo p, etc.
Cada declaración consta de un atributo y un valor
propiedad representa el nombre del atributo que se va a formatear, value representa el valor del atributo que se va a formatear y cada atributo tiene cada valor.

selector{property:value;property:value;…}

Insertar hoja de estilo CSS

Formato:

CSS selector{
	 Attribute name: attribute value;
	 Attribute name; attribute value;
	...
}

Ejemplo:

p{
    color: blue;
}

Características de CSS

Herencia
  • En cascada significa que cuando el mismo archivo HTML hace referencia a varios archivos de hoja de estilos, el explorador aplicará estilos según la jerarquía de definiciones de estilo.Si no se tiene en cuenta la prioridad del estilo, generalmente se sigue el «principio de prioridad reciente».
  • La base de la capacidad de los estilos CSS para controlar el contenidoRelación de herencia familiar en el diagrama de estructura de documentos HTML.
  • El elemento secundario hereda el estilo del elemento primario y solo hereda los atributos que no están definidos por sí mismo.

Selector de etiquetas

El selector de etiquetas hace referencia al uso de nombres de etiqueta HTML como selectores, categorizados por nombres de etiquetas y especifican un estilo CSS unificado para un determinado tipo de etiqueta en la página. El formato de sintaxis básico es el siguiente:

Nombre de etiqueta {atributo 1: valor de atributo 1; atributo 2: valor de atributo 2; … atributo n: valor del atributo n;}

Pros y contras de usar selectores de etiquetas
  • Ventajas: Puede unificar rápidamente estilos para el mismo tipo de etiquetas en la página.
  • Desventajas: incapaces de diseñar estilos diferenciados, a veces interfieren entre sí

Selector de clases

El selector de clases se identifica mediante «.» (notación de puntos), seguido del nombre de clase y su formato de sintaxis básico es el siguiente:

. Nombre de clase {atributo 1: valor de atributo 1; atributo 2: valor de atributo 2; … atributo n: valor del atributo n;}

En esta gramática, el nombre de clase es el valor del atributo de clase del elemento HTML y la mayoría de los elementos HTML pueden definir el atributo de clase. La mayor ventaja of selectores de clase es que puede definir estilos separados o idénticos para objetos de elemento

Método

  1. El primer paso: defina el nombre de clase de la etiqueta que necesita ser styled, es decir, establezca un atributo de clase en la etiqueta y asigne un valor al atributo class.El valor asignado es el nombre de clase.
  2. Paso 2: Utilice el nombre de clase en CSS para encontrar la etiqueta correspondiente en el archivo html.Para agregar un punto sólido negro delante del nombre de la clase.

Ejemplo:

<style>
        .p1{
			color:blue;
		}
</style>
<p class="p1">
                 This is the use of class selector
</p>
Atención del nombre de la clase
  • Los números no se pueden utilizar como el primer carácter del nombre de la clase, y no puede funcionar en Mozilla o Firefox.
  • Los nombres de clase distinguen estrictamente entre mayúsculas y minúsculas y, por lo general, usan caracteres en minúsculas en inglés.
  • No se recomienda utilizar el subrayado «_» para nombrar selectores CSS.
  • Trate de no abreviar, a menos que pueda entender las palabras de un vistazo.

La misma etiqueta puede definir el mismo nombre de clase y también se pueden definir etiquetas diferentes como el mismo nombre de clase.

Selector de ID

El selector de IDENTIFICADOR utiliza «#» para la identificación, seguido del nombre del identificador, y su formato de sintaxis básico es el siguiente:

#ID {atributo 1: valor de atributo 1; atributo 2: valor de atributo 2; … atributo n: valor del atributo n;}

En esta gramática, el nombre del identificador es el valor del atributo ID del elemento HTML y la mayoría de los elementos HTML pueden definir el atributo ID.El valor id de un elemento es único y solo puede corresponder a un elemento específico del documento.

Método:

  1. El primer paso: en el documento html, establezca el atributo id en una etiqueta y, a continuación, establezca el valor del atributo para el atributo,El valor del atributo es el nombre del identificador.
  2. Paso 2: Utilice el nombre del id como selector en el archivo CSS,Pero necesitas agregar # delante del nombre del id.
    Ejemplo:
        #np1{
            background-color: cyan;
        }
<div class="p1" id="np1">
                 Hello there, 
        <div>
                           world!
        </div>
</div>

Nota: El nombre del id es único en todo el documento y no se puede duplicar.


* En CSS, es un comodín, que coincide con cualquier etiqueta.
Ejemplo:

		*{
            margin: 0;/*Margin*/
            padding: 0;/*Inner margin*/
        }

Esto es para eliminar los márgenes internos y externos. Hablaré de ello en detalle más tarde, así que me lo saltaré aquí.

Declaración css simple

Utilidad Gramática Nota
Establecer el tamaño de fuente tamaño de fuente El contenido añadido es del mismo tamaño que la ropa que compraste, xl es mayor que l y mayor que s. También puede establecer el tamaño de fuente con un valor numérico y seleccionar la unidad necesaria
Si la fuente es en negrita font-weight Añadir contenido como audaz, más audaz (un poco más grueso que audaz), más ligero (un poco más delgado que audaz) o valor en negrita, ya que hay varias opciones para elegir
Si la fuente está inclinada estilo fuente Si quiere añadir cursa
Establecer fuente de caracteres font-family Sólo tiene que añadir cualquier fuente que necesite. Si la fuente se escribe con varias palabras, es necesario incluirla entre comillas simples, puede escribir el nombre de la fuente china directamente, puede agregar más de una, de acuerdo con el principio de proximidad
Gorras pequeñas variante de fuente Convierte letras minúsculas en letras mayúsculas, pero la cabeza sigue siendo la misma, si hay letras minúsculas. Puede agregar small-caps más tarde
Establecer sangría de texto con sangría de texto Agregue caracteres de sangría, generalmente establezca la primera línea en sangría de dos caracteres 2em
Establecer alineación de texto alineación de texto alineación central centroizquierda alinear izquierdaderecha alinear derechajusty justificado en ambos extremos
Establecer espaciado de línea alineación de texto Los valores se pueden agregar, preferiblemente en forma de em, que es el mismo que el múltiplo en la palabra, por ejemplo 1,5em es 1,5 veces el espaciado de línea
Texto modificado texto-decoración Puede agregar líneas al texto, sobrelínea, subrayado subrayado y tachado de línea. También puede establecer el estilo y el color, para eliminar el subrayado del hipervínculo, es necesario añadir ninguno
Conversión de casos transformación del texto mayúsculas mayúsculas mayúsculas y minúsculas de letras minúsculas, mayúsculas y minúsculas
Modificar el color Color Puede agregar directamente el nombre en inglés del color en la parte posterior, y también puede utilizar el formato RGB o el formato hexadecimal
Espaciado de caracteres espaciado de letras Sólo tiene que añadir un valor
Espaciado de palabras en inglés espaciado de palabras Sólo tienes que añadir un valor, sólo es útil para las palabras en inglés
Establecer la dirección del texto Dirección ltr es el valor predeterminado. La dirección del texto es de de izquierda a derecha, y la dirección del texto rtl es de derecha a izquierda.
Añadir fondo, añadir cuerpo color de fondo Sólo tiene que añadir el color que necesita para agregar
Añadir una imagen de fondo background-image:url (dirección de imagen) Sólo tiene que añadir su propia dirección de imagen a la dirección de la imagen
Azulejo de imagen de fondo repetición de antecedentes repetir baldosa horizontal y verticalmente, repetir-x azulejos horizontalmente, repetir-y azulejos verticalmente, no repetir no azulejos
Posición de la imagen de fondo posición de fondo icono centralbaldosa izquierdabaldosa derechaesquina superior derecha derecha derecha esquina inferior derecha derecha esquina superior izquierda superior izquierda esquina inferior izquierda inferior izquierda esquina izquierda, también puede utilizar el método numérico, el método relativo 50% 50% representa la ubicación 50% de ancho y 50% de longitud, 60px 30px representa la anchura 60px y la longitud 30px
Establezca el tamaño de la imagen de fondo tamaño de fondo 100% 100% significa horizontal 100%, vertical 100%, contienen significa la mayor proporción sin distorsión, la cubierta también es la mayor, pero independientemente de si la distorsión no está distorsionada
La imagen de fondo sigue siendo background-attachment: fijo; En este caso, no se moverá con el deslizamiento de la marcha, sino que se arreglará

Aplicación de código de ejemplo

<!DOCTYPE html>
<html lang="en">
 <head> 
  <meta charset="UTF-8" /> 
  <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
  <title>Document</title> 
  <style>
    body{
        background-color:#cccccc;
    }
    h1{
        color: white;
        font-weight:lighter;
        background-color: red;
    }
    .c0{
        color: white;   
        font-family:Italics;     
        font-style:italic;
        direction:rtl;

}   
    .c1{
        color: red;
        font-size:24px;
        font-weight: 500;
        font-family:  Song Ti;
        font-weight:bold;
    }
</style> 
 </head> 
 <body> 
  <h1>Japanese</h1> 
  <hr /> 
  <p class="c0">Category: Mood</p> 
  <p class="c1">Feminine beauty</p>  Abstract: Charismatic women are beautiful. She makes the world warm, keeps the world youthful and vigorous forever, and makes the world always full of charm and romance. What is charm? The explanation in the dictionary is the power to attract people. It is often heard that someone evaluates a woman like this: she is not beautiful, but she is very attractive. Charm is a deep level of beauty, better than all external beauty Both are full of vitality, making people unforgettable at first sight....... View full text 
  <br />
  <br /> 
  <p class="c2">2007.3.8 13:27 Author: Poetry in Hong Yayun references: 6 | <a style="text-decoration:none" href="http://www.baidu.com">Favorites</a>  | Comments: 56 </p> 
  <p class="c0">Category: Emotional Station</p> 
  <p class="c1">Emotional analysis: some secret words for men in their 30s</p>  Summary: 1. Don't give up ideals and dreams. There will be colors in the dream life; second, there is a set of top suits, or a classic watch, or a luxurious lighter, or. In short, there is something worth telling about history that can be passed on to one's own children; third, reselect one's own friends. Keep one or two confidants and spend your whole life to maintain it; four or thirty years old. Know a lot of details. Including when wearing a suit... more 
  <br />
  <br /> 
  <p class="c2">2011.11.9 00:17 Author: Poetry in Hong Yayun references: 0 | <a style="text-decoration:none" href="http://www.baidu.com">Favorites</a>  | Comments: 1</p> 
  <p class="c0">Category: Appreciation</p> 
  <p class="c1">Beautiful and picturesque! World ocean photography masterpieces announced (Photos) </p>  Abstract: According to foreign media reports, the world’s outstanding ocean photography photos have been announced recently, from which we can enjoy beautiful ocean scenery and learn about many peculiar ocean creatures. In addition, the photographer’s superb photography skills are also amazing. The following are excellent works of ocean photography in 2010. Photographer's comment: "At night, spotted dolphins off the coast of Little Bahamas dive into the deep sea to look for squid... more 
  <p class="c2">  2011.10.28 23:53 Author: Poetry in Hong Yayun references: 1 | <a style="text-decoration:none" href="http://www.baidu.com">Favorites</a>  | Comments: 1 </p>  
 </body>
</html>

Imagen de efecto

Selector de pseudoclase

Los selectores de pseudoclase y los selectores de pseudoelementos pueden especificar estilos para resultados no específicos en el documento o especificar estilos para el estado de determinados elementos (incluido el propio documento). Aplica estilos basados en ciertas condiciones en lugar de la estructura del documento.

El método de uso del selector de pseudoclase es el siguiente:
HTML markup pseudo-class name {pseudo-class name: attribute value; attribute name: attribute value; .....}
Las pseudoclases de uso común se muestran en la tabla siguiente:

Nombre de pseudoclase Descripción
:enlace El estilo antes de que no se coloque el ratón
:visitado El estilo de los hipervínculos visitados
:enfoque Cuando el elemento se denomina foco, a menudo se utiliza para los elementos de formulario
:hover Se utiliza cuando el mouse está en el elemento, pero no se ha activado ni se ha hecho clic, por ejemplo, el puntero del mouse puede permanecer en un hipervínculo y :hover indicará el hipervínculo

Uso de selectores de pseudoclase

Ejemplo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The use of CSDN Dong Mengyu pseudo-classes</title>
    <style>
        a:link{/*The initial color of the hyperlink is blue*/
            color: blue;
        }
        a:visited{/*After the hyperlink is clicked once, the color becomes darkslategrey;*/
            color: darkslategrey;
        }
        a:hover{/*When the mouse is on the hyperlink, the hyperlink color is yellow*/
            color: yellow;
        }
        a{
            font-size: 32px;
        }
    </style>
</head>
<body>
    <div>
        <a href="https://blog.csdn.net/lolly1023">CSDN: Dong Mengyu</a>
    </div>
</body>
</html>

El efecto es el siguiente:

El azul es el color de ajuste inicial, y el amarillo es el color del ratón atascado en la conexión.
Instrucciones para el uso de pseudoclases:
El orden de las pseudoclases en la etiqueta a debe ser LVHA (: link:visited:focus:hover). En la definición CSS, a:hover debe colocarse después de un:link y a:vistied para ser válido. En la definición CSS , A:active debe colocarse después de a:hover para ser eficaz.

Selector de pseudoelemento

El método de uso del selector de pseudoelemento es el siguiente:
Marcado HTML: pseudoelemento (nombre del atributo: valor del atributo; nombre del atributo: valor del atributo;…)
Los pseudoelementos de uso común se muestran en la tabla siguiente:

Nombre del pseudoelemento Descripción
:primera letra Agregue un estilo especial a la primera letra del texto, asociado con elementos de nivel de bloque
:primera línea Añadir un estilo especial al viaje inaugural en el texto
:antes Agregar contenido antes del elemento, el pseudoelemento predeterminado es un elemento en línea
:después Agregar contenido después del elemento

Uso de pseudoelementos

Ejemplo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSDN Dong Mengyu's use of pseudo-elements</title>
    <style>
        /*The first letter of the first line changes*/
        div::first-letter{/*Set the size of the first word at the beginning of the first paragraph to 64px*/
            font-size: 64px;
        }
        /*Modify all the first line*/
        div::first-line{/*Set the background color of the first line to red*/
            background-color: red;
        }
        /*Add content in front of the text*/
        div::before{/*Add content at the beginning, you need to use content to add*/
            /*Add text content*/
            content: 'CSDN';
            font-style: italic;
        }
        /*Add content after the text*/
        div::after{/*Add content at the beginning, you need to use content to add*/
            content: 'Dong Mengyu';
            color: blue;
        }
    </style>
</head>
<body>
    <div>
                 Examples of pseudo-elements
    </div>
</body>
</html>

El efecto es el siguiente:

Selector de intersección

  • El selector de intersección consta de dos selectores y el resultado es seleccionar la intersección de los dos rangos de elementos de cuadrícula.
  • Requisitos: El primer selector de la intersección debe ser un selector de marcas y el segundo debe ser un selector de clases o un selector de id.
  • No puede haber espacios entre los dos selectores, y deben escribirse consecutivamente.

Uso del selector de intersección

Ejemplo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The use of Dong Mengyu intersection selector</title>
    <style>
        p.p1{/**Use the intersection selector, select the content of the p tag and the class selector as p1, and then modify it/
            font-size: 32px;
        }
    </style>
</head>
<body>
    <div>
        <p class="p1">I used the intersection selector</p>
        <p>I did not use the intersection selector</p>
    </div>
</body>
</html>

El efecto es el siguiente:

.